Click here to Skip to main content
Click here to Skip to main content

Streaming Chart Images as FileResult from MVC Controllers

By , 10 Mar 2009
 

three_charts.png

Introduction

Not a lot of server controls play nicely with the ASP.NET MVC framework; Microsoft Chart does. To implement a true MVC design pattern, the Controller should relate to the View any dependencies from the Model (data). This project shows how the Microsoft Chart controls can be streamed from the Controller into an MVC View. The article assumes a basic knowledge of the ASP.NET MVC framework (Dino Esposito article here) and the restrictions associated with using server controls (no control-level events in the code-behind and the control won’t be able to postback).

Background

The use of the Microsoft Chart in the MVC framework is fairly well documented. Code-Inside Blog International gives a good introduction here. The author's examples have been included on the first two links on the default page of the project. Reading the responses to the article, I stumbled onto an interesting post by Florian (January 18 2009 @ 10:46 pm). He states:

A third option that works very well is to have the following code in your ASPX:

<img src=”/Product/GetChart” alt=”Chart” />

This calls the GetChart action on the myProduct controller. The action creates a chart in memory, saves the chart as an image to a temp folder, and then streams the image of the chart to the client. By the way, the action returns a FileResult.

The main advantage of this third method is that it does not require the ASPX page to have any ASP server controls, and subsequently no code-behind is needed.

I looked into FileResult (derived from ActionResult) and found an interesting article on thuban.org :: Keith J. Farmer's blog here. Adopting this code, I quickly found the overload for the Chart.SaveImage that used a stream and plugged it all together (see below).

The View code:

streaming_view.png

The Controller code:

get_chart_action_result.png

Using the code

To run the project, the following components must be installed:

To use the mechanisms discussed in this article in your own project, you will need these additional steps:

  • add the sections shown in the Code-Inside Blog International article to the web.config.
  • add the chart or img markup (depending on the approach).
  • add the code-behind (method 2) or the controller methods (method 3).
  • include the FileResult class, if using method 3.

The examples shown are simplified, and do not draw data from a database.

Points of interest

The streaming of the image plugged nicely into the Chart API - they catered for this Use Case. On the downside, the data-binding on this release of the Microsoft Chart Controls for Microsoft .NET Framework 3.5 is quite primitive and is not LINQ or Entity friendly.

History

  • 2009-Mar-09 - Typos and source-code update.
  • 2009-Mar-05 - First submission.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Nic_Roche
Software Developer Encore Software
Australia Australia
Member
Contractor in Desktop and Web applications.
Gold Coast, Queensland.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralAjax and multiple graphsmembersalmoliv28 Sep '10 - 14:47 
GeneralThis rules! [modified]memberKarsten Januszewski3 Mar '10 - 11:24 
GeneralVisual Basic Version of the article needed!memberphillipparrin15 Dec '09 - 8:53 
GeneralRe: Visual Basic Version of the article needed!memberNic_Roche15 Dec '09 - 11:36 
QuestionWhat if i have to show tooltips in the charts??memberM Ali Raza11 Aug '09 - 0:40 
AnswerRe: What if i have to show tooltips in the charts??memberNic_Roche11 Aug '09 - 10:25 
QuestionASP.Net + MVC + Chart Drill DownmemberJaisrinivasan29 Jul '09 - 4:26 
AnswerRe: ASP.Net + MVC + Chart Drill DownmemberNic_Roche29 Jul '09 - 10:42 
GeneralSource code file not available to downloadmemberptpatil24 Jun '09 - 18:38 
GeneralRe: Source code file not available to downloadmemberNic_Roche29 Jul '09 - 10:43 
GeneralMVC RC2memberRichard Deeming10 Mar '09 - 9:26 
GeneralRe: MVC RC2memberNic_Roche10 Mar '09 - 20:53 
GeneralRe: MVC RC2memberRichard Deeming11 Mar '09 - 3:01 
Phil Haak has a couple of good blog posts which cover most of the changes:
MVC RC1[^]
MVC RC2[^]
 

 
I think it may be "better" to define a separate ChartResult class to render the chart to the response. This would probably be easier to test, and would isolate the details of rendering the chart in a single class.
 
For example:
 
using System;
using System.IO;
using System.Web;
using System.Web.Mvc;
using System.Web.UI.DataVisualization.Charting;
 
namespace Mvc_Chart.Controllers
{
    public class ChartResult : FileResult
    {
        private const int _bufferSize = 0x1000;
        
        public ChartResult(Chart chart, ChartImageFormat imageFormat) : base(MapImageFormatToMimeType(imageFormat))
        {
            if (null == chart) throw new ArgumentNullException("chart");
            
            this.Chart = chart;
            this.ImageFormat = imageFormat;
        }
        
        public ChartResult(Chart chart) : this(chart, ChartImageFormat.Png)
        {
        }
        
        public Chart Chart
        {
            get;
            private set;
        }
        
        public ChartImageFormat ImageFormat
        {
            get;
            private set;
        }
        
        private static string MapImageFormatToMimeType(ChartImageFormat imageFormat)
        {
            switch (imageFormat)
            {
                case ChartImageFormat.Png:
                    return "image/png";
                    
                case ChartImageFormat.Jpeg:
                    return "image/jpeg";
                    
                case ChartImageFormat.Gif:
                    return "image/gif";
                    
                case ChartImageFormat.Bmp:
                    return "image/bmp";
                    
                case ChartImageFormat.Tiff:
                    return "image/tiff";
                
                // TODO: MIME types for EMF?
                // case ChartImageFormat.Emf:
                // case ChartImageFormat.EmfPlus:
                // case ChartImageFormat.EmfDual:
                
                default:
                    throw new ArgumentException("Unsupported format");
            }
        }
        
        protected override void WriteFile(HttpResponseBase response)
        {
            // NB: Can't save directly to the output stream,
            // as most image formats require a seekable stream.
            
            using (var imageStream = new MemoryStream())
            {
                this.Chart.SaveImage(imageStream, this.ImageFormat);
                imageStream.WriteTo(response.OutputStream);
            }
        }
    }
}
 
public ChartResult GetChart()
{
    var chart = new Chart();
    ...
    
    return new ChartResult(chart, ChartImageFormat.Png)
    {
        FileDownloadName = "Yo.png"
    };
}

 



"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer


GeneralRe: MVC RC2memberNic_Roche11 Mar '09 - 20:59 
GeneralRe: MVC RC2memberNic_Roche11 Mar '09 - 21:00 
GeneralNice Approachmemberericness8 Mar '09 - 18:08 
GeneralRe: Nice ApproachmemberNic_Roche9 Mar '09 - 1:28 
QuestionNice workmemberkraftspl8 Mar '09 - 0:30 
AnswerRe: Nice work [modified]memberNic_Roche8 Mar '09 - 1:18 
GeneralRe: Nice workmemberkraftspl9 Mar '09 - 10:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 10 Mar 2009
Article Copyright 2009 by Nic_Roche
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid