August 2011 - Posts

Using the .NET Chart API to add sparklines to your MVC site

In my last post, I introduced sparklines and showed you how to generate them using the Google Chart API.  Using an external API may not be appropriate for all applications, so here is a way to generate the sparkline using the .NET Chart API.

Over at the Better Dashboards Blog, they provide some sample code for calling the chart API.  The following shows how to make it reusable for your MVC application.

First, we'll create a custom ActionResult to return the image for our sparkline:

    public class SparklineResult : FileResult
    {
        IEnumerable<float> samples;
        int SparklineWidth;
        int SparklineHeight;
        public SparklineResult(int width, int height, IEnumerable<float> samples) : base("image/png")
        {
            this.samples = samples;
            this.SparklineHeight = height;
            this.SparklineWidth = width;
        }
        protected override void WriteFile(HttpResponseBase response)
        {
            var sparklineImage = GetSparkLineImage(samples, SparklineWidth, SparklineHeight);
            response.ContentType = "image/png";
            response.BinaryWrite(sparklineImage);
        }
        private static byte[] GetSparkLineImage(IEnumerable<float> samples, int width, int height)
        {
            var chart = new Chart();
            var series = new Series();
            chart.Series.Add(series);
            // Sparklines use the 'Spline' chart type to show a smoother trend with a line chart
            series.ChartType = SeriesChartType.Spline;
            // Since the line is the only thing you see on the chart, you might want to
            // increase its width. Interestingly, you need to set the BorderWidth property
            // in order to accomplish that.
            series.BorderWidth = 2;
            // Add samples to the series
            int i = 0;
            foreach (var sample in samples)
            {
                i++;
                // Add 5 to the sample so line does not get cut off at the bottom of the image
                chart.Series[0].Points.AddXY(DateTime.Now.AddDays(i), sample + 5);
            }
            // Start hiding both sets of axes, labels, gridlines and tick marks
            var chartArea = new ChartArea();
            chart.ChartAreas.Add(chartArea);
            chartArea.AxisX.LabelStyle.Enabled = false;
            chartArea.AxisY.LabelStyle.Enabled = false;
            chartArea.AxisX.MajorGrid.Enabled = false;
            chartArea.AxisY.MajorGrid.Enabled = false;
            chartArea.AxisX.MajorTickMark.Enabled = false;
            chartArea.AxisY.MajorTickMark.Enabled = false;
            chartArea.AxisX.LineWidth = 0;
            chartArea.AxisY.LineWidth = 0;
            chartArea.AxisY.Minimum = 0;
            // Add an extra 5 pixels since the samples were adjusted up by 5
            // this prevents the line from being truncated
            chartArea.AxisY.Maximum = 105;
            // Re-adjust the size of the chart to reduce unnecessary white space
            chart.Width = width;
            chart.Height = height;
            // Get bytes of PNG image
            var s = new MemoryStream();
            chart.SaveImage(s, ChartImageFormat.Png);
            s.Position = 0;
            return s.ToArray();
        }
    }

Next, we'll utilize the SparklineResult in a controller. The controller will serve the image data for the sparkline back to the calling page.

    public class ChartController : Controller
    {
        public ActionResult Sparkline(int width, int height, string samples)
        {
            return new SparklineResult(width, height, (from s in samples.Split(',') select float.Parse(s)).ToArray());
        }
    }

Next, we'll create a HTML helper method to generate the img tag which will fetch the image from our controller.

        public static MvcHtmlString DrawSparkline(this HtmlHelper helper, int width, int height, IEnumerable<int> plotData)
        {
            string sparkUrl = "<img src='/chart/sparkline?width={0}&height={1}&samples={2}'/>";
            string sparkLine = String.Format(sparkUrl, width, height, String.Join(",", plotData));
            return MvcHtmlString.Create(sparkLine);
        }

Now we can call the helper method from our Razor template:

       @Html.DrawSparkline(70, 20, new int[14] { 1, 4, 2, 6, 20, 30, 1, 23, 14, 2, 41, 2, 33, 21 })

Which produces the following sparkline:

 

You can download my sample project that puts it all together.  This includes both the Google API & .NET API methods.

Posted by brian_ritchie | 8 comment(s)
Filed under: , , , ,

Adding sparklines to your MVC site using the Google Chart API

Sparklines present trends and variations associated with some measurement in a very compact form.  The term & concept was proposed by Ed Tufte.  This form of information graphic has become very popular for dashboards.  In this post, I'll show how add sparklines to your site using a custom HTML Helper method to generate code accessing the Google Chart API. In my next post, I'll show you how to add sparklines using the .NET charting API.

The folks over at Data Driven wrote a post about using the Google Chart API to render a sparkline.  The following shows how to take this concept & make it reusable by your MVC application.

Code for the extension method:

        public static MvcHtmlString DrawSparkline(this HtmlHelper helper, int width, int height, IEnumerable<int> plotData,
            string bgColor, string lineColor, string labelColor)
        {
            int? max = plotData.Max();
            int? min = plotData.Min();
            string list = String.Join(",", plotData);
            string sparkUrl = "<img src='http://chart.apis.google.com/" +
                 "chart?cht=lc&chf=bg,s,{6}&cgh=0,50,1,0&chds={0},{1}&chs={2}x{3}&chd=t:{4}&chco={8}" +
                 "&chls=1,1,0&chm=o,{7},0,20,4&chxt=r,x,y&chxs=0,{7},11,0,_|1,{7},1,0,_|2,{7},1,0,_&chxl=0:|{5}|1:||2:||'/>";
            string sparkLine = String.Format(sparkUrl, min, max, width, height, list, plotData.Last(), bgColor, labelColor, lineColor);
            return MvcHtmlString.Create(sparkLine);
        }

And here is an example of calling the HTML helper from a MVC Razor template:

@Html.DrawSparkline(70, 20, new int[14] { 1, 4, 2, 6, 20, 30, 1, 23, 14, 2, 41, 2, 33, 21 }, "ffffff", "999999", "990000")

Which produces the following sparkline:

Posted by brian_ritchie | 4 comment(s)
Filed under: , , ,

Scaling Out .NET Presentation at Jax Code Camp 2011

Today at the Jax Code Camp I gave a presentation on scaling out your .NET applications by leveraging IIS7, AppFabric, Web Farm Framework, and Web Deploy.  Thanks to everyone how come out to the session.

I've posted the presentation over at SlideShare and here are some related blog posts that I mentioned during the talk:

Scaling Out .NET

Need further reading?

» Web Farm Framework
» Windows AppFabric
» Other
˃Memcached ASP.NET Providers
http://memcachedproviders.codeplex.com/

F5 Add-on for Web Farm Framework

Gupreet over on the IIS.NET site posted a sample for integrating an F5 load balancer with the Web Farm Framework.  It works well, but isn't configurable.  I started adding my own configuration, but artisticcheese posted a project to CodePlex that already has this functionality.

To install, download the extension and perform the following: 

  1. Create pool on F5 load balanacer with exactly the same name on WFF. Do not add any farm members yet.
  2. Stop WFF service
  3. Create folder "%programfiles%\IIS\Microsoft Web Farm Framework\extensions" and put all files in distribution into that folder
  4. Modify "F5LoadBalancer.dll.config" file to point to active node of F5 loadbalancer and authentication credentials
  5. Copy "icontrol.dll" into "%programfiles%\IIS\Microsoft Web Farm Framework"
  6. Open "%systemroot%\system32\inetsrv\config\applicationHost.config" and edit XML node below by adding attribute in bold <webFarm name="DevWebFarm" enabled="true" primaryServer="webnode1" loadBalancerProvider="F5">
  7. Start WFF service

iControl.dll is an assembly provided by BigIP giving you a .NET API to control your F5 Local Traffic Balancer.

Now that you have it installed, WFF will automatically take nodes online & offline thru the F5 as needed.  This supports rolling deployments and more.

Posted by brian_ritchie | 5 comment(s)
Filed under: , , , ,
More Posts