• Using ASP.NET Charting in ASP.NET MVC

    by Venkata Koppaka | Mar 31, 2010

    In this blog post I will talk about how to use ASP.NET Charting controls( which Microsoft announced last year) in a ASP.NET MVC application.

    If you want to read more about ASP.NET Charting Controls here is a link to Scott Gu's Blog Post : http://weblogs.asp.net/scottgu/archive/2008/11/24/new-asp-net-charting-control-lt-asp-chart-runat-quot-server-quot-gt.aspx.

    I will be using Streaming Chart Images as FileResult from MVC controller article on Code Project by Nic Roshe, to read more about the article here is a linkhttp://www.codeproject.com/KB/aspnet/MvcChartControlFileResult.aspx?msg=2959619.

    Lets get started, create a new ASP.NET MVC application and add Reference toSystem.Web.DataVisualization. Add a Class to your project called ChartResult(Name can be anything I am just reusing the name used by Nic Roshe in the codeproject article). This ChartResultClass should derive from a FileResult Class. This Class would map and Image to a known MIME type. Further more since this class extends from FileResult Class System.Web.Mvc we get to override aWriteFile method which takes in a HttpResponseBase object. The WriteFile method can then be used to create a Output memory stream.

    Here is how the Class would look like -

    1     public class ChartResult : FileResult 
    2     { 
    3         private const int _bufferSize = 0x1000; 
    4  
    5         public ChartResult(Chart chart, ChartImageFormat imageFormat) 
    6             : base(MapImageFormatToMimeType(imageFormat)) 
    7         { 
    8             if (null == chart) throw new ArgumentNullException("chart"); 
    9  
    10             this.Chart = chart; 
    11             this.ImageFormat = imageFormat; 
    12         } 
    13  
    14         public ChartResult(Chart chart) 
    15             : this(chart, ChartImageFormat.Png) 
    16         { 
    17         } 
    18  
    19         public Chart Chart 
    20         { 
    21             get; 
    22             private set; 
    23         } 
    24  
    25         public ChartImageFormat ImageFormat 
    26         { 
    27             get; 
    28             private set; 
    29         } 
    30  
    31         private static string MapImageFormatToMimeType(ChartImageFormat imageFormat) 
    32         { 
    33             switch (imageFormat) 
    34             { 
    35                 case ChartImageFormat.Png: 
    36                     return "image/png"; 
    37  
    38                 case ChartImageFormat.Jpeg: 
    39                     return "image/jpeg"; 
    40  
    41                 case ChartImageFormat.Gif: 
    42                     return "image/gif"; 
    43  
    44                 case ChartImageFormat.Bmp: 
    45                     return "image/bmp"; 
    46  
    47                 case ChartImageFormat.Tiff: 
    48                     return "image/tiff"; 
    49  
    50                 // TODO: MIME types for EMF? 
    51                 // case ChartImageFormat.Emf: 
    52                 // case ChartImageFormat.EmfPlus: 
    53                 // case ChartImageFormat.EmfDual: 
    54  
    55                 default: 
    56                     throw new ArgumentException("Unsupported format"); 
    57             } 
    58         } 
    59  
    60         protected override void WriteFile(HttpResponseBase response) 
    61         { 
    62             // NB: Can't save directly to the output stream, 
    63             // as most image formats require a seekable stream. 
    64  
    65             using (var imageStream = new MemoryStream()) 
    66             { 
    67                 this.Chart.SaveImage(imageStream, this.ImageFormat); 
    68                 imageStream.WriteTo(response.OutputStream); 
    69             } 
    70         } 
    71     } 

    Please note using the ChartResult and FileResult Classes, the ASP.NET Charting Control will render as a Image file on your MVC View. Now lets see how this ChartResult can be used to render a ASP.NET Charting graph as a Image.

    Lets look at how the View Page would look like -

    There are two possibilities to render the image, we could create a ViewPage in MVC which just renders the Image or just use an <img> tag and specify its source to be the Action Method on the Controller.

    1         <a href="Home/BarChart">Bar Chart</a><br /> 
    2         <a href="Home/PieChart">Pie Chart</a><br /> 
    3         <img src="Home/LineChart" alt="Line Chart" /> 

    The Home/BarChart and Home/PieChart are two MVC views which are just used for rendering purpose. If you feel that its a waste to create a view just to render an image you are right :). Hence the third line in the above snippet shows how the image tags src attribute can be used to render the image. We give the src attribute an Action Method which returns a FileResult.

    Now here is how the Controller Code would look like,(please note this code need not be in a controller for sake of easy demo purposes I am putting it in a controller.)

    Here is how a BarChart can be  constructed.

     

    1         public ChartResult BarChart() 
    2         { 
    3             Chart chart = new Chart(); 
    4             chart.Width = 480; 
    5             chart.Height = 300; 
    6             chart.RenderType = RenderType.ImageTag; 
    7             chart.Palette = ChartColorPalette.Fire; 
    8             Title t = new Title("Bar Chart", Docking.Left, new Font("Trebuchet MS", 14, FontStyle.Bold), Color.Black); 
    9             chart.Titles.Add(t); 
    10  
    11  
    12             chart.BorderSkin.SkinStyle = BorderSkinStyle.Emboss; 
    13             chart.BorderlineWidth = 2; 
    14             chart.BorderlineColor = Color.Black; 
    15             chart.BorderlineDashStyle = ChartDashStyle.Solid; 
    16  
    17             chart.ChartAreas.Add("Default"); 
    18  
    19             chart.Legends.Add("Legend1"); 
    20  
    21             chart.Series.Add("Series 1"); 
    22             chart.Series.Add("Series 2"); 
    23  
    24             List<int> data = new List<int>(); 
    25             data.Add(3); 
    26             data.Add(9); 
    27             data.Add(5); 
    28             data.Add(2); 
    29             data.Add(4); 
    30             data.Add(7); 
    31  
    32             //Series 1 
    33             foreach (int value in data) 
    34             { 
    35                 chart.Series["Series 1"].Points.AddY(value); 
    36             } 
    37  
    38             //Series 2 
    39             foreach (int value in data) 
    40             { 
    41                 chart.Series["Series 2"].Points.AddY(value - 1); 
    42             } 
    43  
    44             return new ChartResult(chart, ChartImageFormat.Png); 
    45  
    46  
    47  
    48         } 

    Here is how a PieChart can be constructed -

    1         public ChartResult PieChart() 
    2         { 
    3             Chart pieChart = new Chart(); 
    4  
    5             pieChart.Width = 480; 
    6             pieChart.Height = 300; 
    7             pieChart.RenderType = RenderType.ImageTag; 
    8             pieChart.Palette = ChartColorPalette.BrightPastel; 
    9             Title t = new Title("Pie Chart", Docking.Left, new Font("Trebuchet MS", 14, FontStyle.Bold), Color.Black); 
    10             pieChart.Titles.Add(t); 
    11  
    12  
    13             pieChart.ChartAreas.Add("defaultChartArea"); 
    14  
    15             pieChart.Legends.Add("Legend1"); 
    16  
    17             pieChart.Series.Add("PieChartSeries"); 
    18  
    19             // Initialize an array of doubles 
    20             double[] yval = { 2, 6, 4, 5, 3 }; 
    21  
    22             // Initialize an array of strings 
    23             string[] xval = { "Peter", "Andrew", "Julie", "Mary", "Dave" }; 
    24  
    25             pieChart.Series["PieChartSeries"].ChartType = SeriesChartType.Pie; 
    26  
    27             // Set series visual attributes 
    28             pieChart.Series["PieChartSeries"].Color = Color.CornflowerBlue; 
    29             pieChart.Series["PieChartSeries"].BackSecondaryColor = Color.SkyBlue; 
    30  
    31  
    32             pieChart.Series["PieChartSeries"].BorderColor = Color.Gray; 
    33             pieChart.Series["PieChartSeries"].BorderWidth = 2; 
    34             pieChart.Series["PieChartSeries"].BorderDashStyle = ChartDashStyle.Solid; 
    35  
    36             pieChart.Series["PieChartSeries"].ShadowOffset = 2; 
    37  
    38  
    39             //Bind the data to chart 
    40             pieChart.Series["PieChartSeries"].Points.DataBindXY(xval, yval); 
    41             //Turn on Legend 
    42             pieChart.Series["PieChartSeries"]["PieLabelStyle"] = "Disabled"; 
    43             //Turn on Labelling 
    44             pieChart.Series["PieChartSeries"]["PieLabelStyle"] = "Inside"; 
    45  
    46  
    47             //Make the Leged to display text and percentage 
    48             pieChart.Series["PieChartSeries"].LegendText = "#AXISLABEL - #PERCENT{P0}"; 
    49  
    50             return new ChartResult(pieChart, ChartImageFormat.Png); 
    51  
    52  
    53         } 

    Here is how a LineChart can be constructed -

    1         public ChartResult LineChart() 
    2         { 
    3  
    4             Chart lineChart = new Chart(); 
    5  
    6             lineChart.Width = 480; 
    7             lineChart.Height = 300; 
    8             lineChart.RenderType = RenderType.ImageTag; 
    9             lineChart.Palette = ChartColorPalette.BrightPastel; 
    10             Title t = new Title("Line Chart", Docking.Left, new Font("Trebuchet MS", 14, FontStyle.Bold), Color.Black); 
    11             lineChart.Titles.Add(t); 
    12  
    13  
    14             lineChart.ChartAreas.Add("defaultChartArea"); 
    15  
    16             lineChart.Legends.Add("Legend1"); 
    17  
    18             lineChart.Series.Add("LineChartSeries"); 
    19  
    20  
    21  
    22  
    23             lineChart.Series["LineChartSeries"].ChartType = SeriesChartType.Line; 
    24  
    25             // Set series visual attributes 
    26             lineChart.Series["LineChartSeries"].Color = Color.Red; 
    27             lineChart.Series["LineChartSeries"].BackSecondaryColor = Color.SkyBlue; 
    28  
    29  
    30             lineChart.Series["LineChartSeries"].BorderColor = Color.Gray; 
    31             lineChart.Series["LineChartSeries"].BorderWidth = 2; 
    32             lineChart.Series["LineChartSeries"].BorderDashStyle = ChartDashStyle.Solid; 
    33  
    34             lineChart.Series["LineChartSeries"].ShadowOffset = 2; 
    35  
    36  
    37             // Populate series with random data 
    38             Random random = new Random(); 
    39             for (int pointIndex = 0; pointIndex < 15; pointIndex++) 
    40             { 
    41                 lineChart.Series["LineChartSeries"].Points.AddY(random.Next(45, 95)); 
    42             } 
    43  
    44  
    45             return new ChartResult(lineChart, ChartImageFormat.Png); 
    46  
    47         } 

    When you run the application you can see the two hyperlinks and an image being rendered on the Home Page

     

     

    Here is a BarCart

     he

    Here is a PieChart -

    Hope this helps,

    Cheers,

    Venkata

    Go comment!
  • Shuffling a List in a random unbiased way

    by Venkata Koppaka | Mar 22, 2010

    I had to come up with a random and unbiased way of shuffling a list of items.

    The first thing that came up to my mind is to sort using a simple for loop which iterates through the list of objects and calls the random function, something like this -

    1 public static void Shuffle<T>(this IList<T> list)   
    2 {   
    3     Random rng = new Random();   
    4     int n = list.Count;   
    5     while (n > 1) {   
    6         n--;   
    7         int k = rng.Next(n + 1);   
    8         T value = list[k];   
    9         list[k] = list[n];   
    10         list[n] = value;   
    11     }   
    12
    13  

    Then I read this post by Jeff Atwood - http://www.codinghorror.com/blog/2007/12/shuffling.htmlwhere he says the best way to do a random unbiased shuffling is to do a sort by a Random Number in .NET world a NewGuid().

    Interesting, so I started to write a little sample to prove  that shuffling using a random sort indeed works. Here is an example snippet.

    1     class Program 
    2     { 
    3         static void Main(string[] args) 
    4         { 
    5             List<Int32> intlist = new List<int>(); 
    6             for (int i = 0; i < 10; i++) 
    7             { 
    8                 intlist.Add(i); 
    9             } 
    10  
    11             intlist = intlist.OrderBy(il => Guid.NewGuid()).ToList(); 
    12  
    13             foreach (int i in intlist) 
    14             { 
    15                 Console.WriteLine(i); 
    16             } 
    17         } 
    18     } 

    Notice at Line number 11 I call a .OrderBy(il=> Guid.NewGuid()).. Man it works like a champ. Here are some test results.

    Iteration 1 :

    3
    2
    9
    6
    1
    0
    8
    7
    4
    5

    Iteration 2 :

    9
    6
    5
    7
    4
    2
    8
    1
    0
    3

    Hope this helps.

    Cheers,

    Venkata


    Go comment!
  • ASP.NET MVC2 Client Validation

    by Venkata Koppaka | Mar 11, 2010

    Some time back I blogged about building my own blog, well I started building it in my spare time. As I mentioned previously, I am using ASP.NET MVC2 and .NET 4 as my platform.

    To start with today, I would walk through how to build a simple contact me page by using ASP.NET MVC2's Model Validation Techniques.

    First let us put the View Page together -

    Below is the content section of my View which takes in a ContactMe as a Model

    Here is the Header -

    1 <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Berkeley.Models.ContactMe>" %> 

    And here is the View Page - Notice the Html.EnableClientValidation() in Line Number about which I will be talking in depth below.

    1  <% Html.EnableClientValidation(); %> 
    2     <% using (Html.BeginForm()) 
    3        {%> 
    4     <fieldset> 
    5         <legend>Contact Me</legend> 
    6         <div class="editor-label"> 
    7             <%= Html.LabelFor(model => model.ContactMe.Name) %> 
    8         </div> 
    9         <div class="editor-field"> 
    10             <%= Html.TextBoxFor(model => model.ContactMe.Name) %> 
    11             <%= Html.ValidationMessageFor(model => model.ContactMe.Name) %> 
    12         </div> 
    13         <div class="editor-label"> 
    14             <%= Html.LabelFor(model => model.ContactMe.Email) %> 
    15         </div> 
    16         <div class="editor-field"> 
    17             <%= Html.TextBoxFor(model => model.ContactMe.Email) %> 
    18             <%= Html.ValidationMessageFor(model => model.ContactMe.Email) %> 
    19         </div> 
    20         <div class="editor-label"> 
    21             <%= Html.LabelFor(model => model.ContactMe.Subject) %> 
    22         </div> 
    23         <div class="editor-field"> 
    24             <%= Html.TextBoxFor(model => model.ContactMe.Subject) %> 
    25             <%= Html.ValidationMessageFor(model => model.ContactMe.Subject) %> 
    26         </div> 
    27         <div class="editor-label"> 
    28             <%= Html.LabelFor(model => model.ContactMe.Message) %> 
    29         </div> 
    30         <div class="editor-field"> 
    31             <%= Html.TextAreaFor(model => model.ContactMe.Message) %> 
    32             <%= Html.ValidationMessageFor(model => model.ContactMe.Message) %> 
    33         </div> 
    34         <p> 
    35             <input type="submit" name="btnSendMessage" value="Send Message" class="stylizedBtn" /> 
    36         </p> 
    37     </fieldset> 
    38     <% } %> 

    Notice the New TextBoxFor , TextAreaFor , ValidationMessageFor - Html Helper methods which are introduced in ASP.NET MVC2 and can take in LINQ Lamda Syntax(which I Love :), I will write a follow up post soon on these methods soon).

    So the view is pretty straight forward which takes in a Model and Displays a simple Insert Form.

    To get Client Side Validation in ASP.NET MVC2 to work all we have to do is drop in references to MicrosoftMVCValidation.js and MicrosoftAjax.js (which ship with the default project template for MVC2) and call Html.EnableClientValidation(). That's it from a View Point of view.

    And from a Model point of view here's how we define validation rules. For this example I am going to be using Entity Framework, so the ORM generates my classes for me. I am going to use something called "buddy classes". Here a more about using buddy classes in Detail.

     Using Data Annotations with Entity Framework Classes -

    After letting EF generate the classes, we write a partial class for the generated class, here is a snippet of how the partial class would look like -

    1 namespace Berkeley.Models 
    2
    3     [MetadataType(typeof(ContactMeValidator))] 
    4     public partial class ContactMe 
    5     { 
    6  
    7     } 
    8  
    9

    Notice above, ContactMe is the class generated by Entity Framework and ContactMeValidator is our buddy class which holds the validation rules. All we are saying above is letting the framework know that if it encounters a Class named ContactMe then its MetaData information is in a Class Named ContactMeValidator.

    Here's what a buddy class with validation logic would look like -

    1 namespace Berkeley.Models 
    2
    3     [Bind(Exclude="ContactMeID")] 
    4     public class ContactMeValidator 
    5     { 
    6         [Required(ErrorMessage="Name is Required")] 
    7         [StringLength(50,ErrorMessage="Name Must be Under 50 Characters")] 
    8         public String Name { get; set; } 
    9  
    10         [Required(ErrorMessage = "Email is Required")] 
    11         [StringLength(50, ErrorMessage = "Email Must be Under 200 Characters")] 
    12         [RegularExpression(@"^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$", ErrorMessage = "Email Not in Valid Format")] 
    13         public String Email { get; set; } 
    14  
    15         [Required(ErrorMessage = "Subject is Required")] 
    16         [StringLength(50, ErrorMessage = "Subject Must be Under 500 Characters")] 
    17         public String Subject { get; set; } 
    18  
    19         [Required(ErrorMessage = "Message is Required")] 
    20         public String Message { get; set; } 
    21  
    22     } 
    23
    Note : I am using .NET 3.5's Data Annotations. with Required,StringLength, and RegularExpressionkeywords.

    That is essentially it. We defined the validation rules in a buddy class which extends to hold the meta data information of classes generated by Entity Framework.

    Here is a screen shot of how the webpage would look like

     

    I will upload a code sample of this example soon.

    Hope this helps,

    Cheers,

    Venkata

    Go comment!