Title: Building your own feedburner stats with the ASP.NET Charting control
Slug: building-your-own-feedburner-stats-with-the-asp-net-charting-control
Date: 2009-01-05 16:45:00
Author: Kartones
Lang: en
Tags: Development, ASP.NET, .NET
Description: A guide on creating custom Feedburner stats using ASP.NET Charting Control.

 <p>I've been using <a href="http://www.feedburner.com">Feedburner</a> for a few years to keep track of RSS statistics (and as a proxy to be able to move my blog without feed readers being affected).</p> <p>Until last week, I used a third party free tool, <strong>Feed Analysis</strong>, to show a graph of the stats of all blogs in Kartones.Net. But after Google bought Feedburner, I decided to migrate the account to Google, and that tool stopped working.</p> <p>I knew the existence of <a href="http://code.google.com/apis/feedburner/awareness_api.html">Feedburner's Awareness API</a> before, but hadn't touched it because I don't know Flash or any other way of creating a stats chart easily.</p> <p>Recently, Microsoft released the new <a href="http://weblogs.asp.net/scottgu/archive/2008/11/24/new-asp-net-charting-control-lt-asp-chart-runat-quot-server-quot-gt.aspx">ASP.NET Charting Control</a>, and I went the "do it yourself" way of implementing my own stats using it.</p> <p>I requested an upgrade of my hosting provider to ASP.NET 3.5 SP1 + installing the chart control (it's a bit dumb to force you to install it instead of deploying an assembly, but ok, I can live with that), and started developing the "chart" page that would display the stats.</p> <p>First, accessing the Feedburner API. You have to activate it in each of your feeds configured in Feedburner:</p> <p><img src="https://images.kartones.net/posts/screenshots/feedburner_awareness_api.jpg"> </p> <p>Then, a simple HTTP Request + Response will fetch the results in XML (I will only list the important fragments of code, not all, and almost no error catchings):</p>

 <code>
 <p>private const string feedburnerAPIURL = <br>    "https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri={0}&amp;dates={1},{2}";</p> <p>...</p> <p>HttpWebRequest request;<br>HttpWebResponse response;<br>string responseXMLString;<br><br>request = (HttpWebRequest)WebRequest.Create(<br>    string.Format(feedburnerAPIURL, feedURI, statsStartingDate, statsEndingDate));<br>request.Method = "GET";<br><br>...</p> <p>response = (HttpWebResponse)request.GetResponse();<br>StreamReader streamReader =<br>    new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(1252));<br>responseXMLString = streamReader.ReadToEnd();<br>streamReader.Close();<br>response.Close();</p> <p>...</p> <p> </p>
 </code>

 <p><code>statsStartingDate</code> and <code>statsEndingDate</code> must be in <i>YYYY-MM-DD</i> format.<br></p>


 <p>We should then check that response code is OK:</p>

  <code>
 <p>...</p> <p>responseXML = new XmlDocument();<br>responseXML.Load(new StringReader(responseXMLString));<br>XmlNode node = responseXML.SelectSingleNode("/rsp");<br>return (node.Attributes.GetNamedItem("stat").Value == "ok");</p> <p>...</p> <p> </p>
 </code>
 <p>I store the opened XmlDocument for the actual stats entries parsing (to avoid reopening it).</p> <p>I've built two tiny structs to store an individual entry and the list of entries (along with max. and min. values of each field). So I fill it:</p>
 <code>
 <p>...</p> <p>XmlNodeList entries = responseXML.SelectNodes("/rsp/feed/entry");<br><br>results.Entries = new FeedburnerEntry[entries.Count];<br>for (int index = 0; index &lt; entries.Count; index++)<br>{<br>    results.Entries[index].Date = <br>        DateTime.Parse(entries[index].Attributes.GetNamedItem("date").Value);<br><br>    results.Entries[index].Circulation = <br>        long.Parse(entries[index].Attributes.GetNamedItem("circulation").Value);<br>             <br>    results.Entries[index].Hits = <br>        long.Parse(entries[index].Attributes.GetNamedItem("hits").Value);<br><br>    results.Entries[index].Reach =<br>        long.Parse(entries[index].Attributes.GetNamedItem("reach").Value);<br>}</p> <p>...</p> <p> </p>
 </code>
 <p>I won't go into details of creating a new chart, <a href="http://code.msdn.microsoft.com/mschart/Release/ProjectReleases.aspx?ReleaseId=1591">the samples</a> are quite good for it, so I'll just point that a lot of configuration can be made in the markup definition of it (2D or 3D, transparency, colors, labels, data types...):</p>
 <code>
 <p>&lt;asp:Chart ID="feedChart" runat="server" Height="480" Width="640" BorderDashStyle="Solid" <br>    imagetype="Png" BorderWidth="1" BorderColor="#6F5F08" TextAntiAliasingQuality="Normal"<br>    Palette="BrightPastel" BackSecondaryColor="#FFFFFF" BackGradientStyle="TopBottom" <br>    backcolor="#DDDBC7" AntiAliasing="All" &gt;<br>    &lt;borderskin skinstyle="Emboss" /&gt;<br>    &lt;legends&gt;<br>        &lt;asp:Legend IsTextAutoFit="False" Name="Default" BackColor="Transparent" <br>            BorderWidth="1" BorderColor="#000000" BorderDashStyle="Solid"<br>            Font="Trebuchet MS, 8.25pt, style=Bold" Alignment="Near" Docking="Bottom" /&gt;<br>        &lt;/legends&gt;<br>        &lt;series /&gt;<br>        &lt;chartareas&gt;<br>            &lt;asp:ChartArea Name="chartArea" BorderColor="#404040"<br>                BackSecondaryColor="White" BackColor="96, 189, 182, 124" <br>                BackGradientStyle="TopBottom" Area3DStyle-Enable3D="true"&gt;<br>                &lt;area3dstyle Rotation="10" Perspective="10" Enable3D="True" <br>                    LightStyle="Realistic" Inclination="10" PointDepth="200" <br>                    IsRightAngleAxes="False" WallWidth="0" IsClustered="False" /&gt;<br>                &lt;axisy LineColor="32, 64, 64, 64" Interval="50"&gt;<br>                    &lt;LabelStyle Font="Trebuchet MS, 8pt" /&gt;<br>                    &lt;MajorGrid LineColor="32, 64, 64, 64" /&gt;<br>                &lt;/axisy&gt;<br>                &lt;axisx LineColor="32, 64, 64, 64" Title="Date" TitleAlignment="Center"<br>                    TitleFont="Trebuchet MS, 12pt" IntervalOffsetType="Days" <br>                    IntervalType="Days"&gt;<br>                    &lt;LabelStyle Font="Trebuchet MS, 8pt" /&gt;<br>                    &lt;MajorGrid LineColor="32, 64, 64, 64" /&gt;<br>                &lt;/axisx&gt;<br>            &lt;/asp:ChartArea&gt;<br>        &lt;/chartareas&gt;<br>&lt;/asp:Chart&gt; </p> <p> </p>
 </code>
 <p>The <i>chart area</i> is where the chart will be painted, and the <i>series</i> (which I leave empty because I fill define and fill it via code) are the groups of points (for example, a series can be one curved line plus one bar graph).</p> <p> </p> <p>Filling the data at code is pretty easy too:</p>
 <code>
 <p>FeedburnerEntryList feed = feedburnerFeed.GetEntries();<br><br>Series circulationGraph = new Series("circulation");<br>circulationGraph.ChartType = SeriesChartType.Spline;<br><br>...<br><br>Series hitsGraph = new Series("Hits");<br>hitsGraph.ChartType = SeriesChartType.Spline;<br><br>...<br><br>for (int index = 0; index &lt; feed.Entries.Length; index++)<br>{<br>    circulationGraph.Points.AddXY(<br>        feed.Entries[index].Date,<br>        feed.Entries[index].Circulation);<br>    hitsGraph.Points.AddXY(<br>        feed.Entries[index].Date, <br>        feed.Entries[index].Hits);<br>}<br><br>feedChart.Series.Add(circulationGraph);<br>feedChart.Series.Add(hitsGraph);</p>
 </code>
 <p> </p> <p>And that's all... a fantastic graph appears:</p> <p><img src="https://images.kartones.net/posts/kartonesblog/feedburner_mschart_graph.jpg"> </p> <p><br></p> <p>I still have to learn how to do some small details, but as anyone can see it is very very easy to use this new control.</p>
