1

A Model contains, amongst other properties, a method which returns an MSChart as a MemoryStream.

In my View I copy the MemoryStream to TempData["Chart"] and then use URL.Action() to call a controllers action to return a FileContentResult using the MemoryStream from TempData.

In the Model

public MemoryStream ViewerChart()
{
    Chart chart = new Chart();
    :
    :
    using (MemoryStream memStream = new MemoryStream())
    {
        chart.SaveImage(memStream, ChartImageFormat.Jpeg);
        return memStream;
    }
}

In the View

@{
    TempData["Chart"]= Model.ViewerChart();
 }
<img alt="Chart" src="@Url.Action("RenderChart")" />

In the Controller

 public ActionResult RenderChart()
 {

   MemoryStream ms = TempData["Chart"] as MemoryStream;
   return File(ms.ToArray(), "image/jpeg");
 }

Despite working OK, this all seems a bit nasty to me, particularly the use of TempData

Is there a better way?

tereško
  • 58,060
  • 25
  • 98
  • 150
K. Bob
  • 2,668
  • 1
  • 18
  • 16
  • Why can't you generate the Chart in the action `RenderChart` ? – Jan Nov 03 '11 at 15:19
  • @Jan - That did cross my mind initially but because the Model already encapsulates this behaviour I didn't think it was such a good idea to repeat it in the Controller. – K. Bob Nov 03 '11 at 15:33
  • How do you retrieve the model object instance in your controller? Can't you just retrieve the model object again in the `RenderChart` action and return its `ViewerChart` property there? – Jan Nov 03 '11 at 16:12
  • @Jan - It's all pretty standard stuff, the controller makes a new instance of the model passing it the userId in the constructor, the Model scoots off to the database and gets the data, the controller passes the model to the View and the view displays the raw data and then I need to do this nasty fiddle with TempData and an extra controller action to render the Chart from the Model in an tag. I could create another instance of the Model in the RenderChart action but that seems just as bad (two trips to the database) as the TempData 'hack'. – K. Bob Nov 03 '11 at 16:30

1 Answers1

0

The acedemic way would be to retrieve the model object again in the RenderChart action and return the chart image to the view.

But i think its a valid approach to store the image in TempData for reducing database roundtrips and boosting performance.

Maybe its even unnecessary to improve the performance. The database will have the data available in its cache when reading it the second time and the additional 10ms needed to fetch the data again might not be noticeable by the user.

At least TempData seems to be the right store because the value is deleted from the collection when its read by the RenderChart action.

Jan
  • 15,802
  • 5
  • 35
  • 59
  • When I use this method in a View with a POST Internet Explorer 9 (but not Chrome) decides it needs to call RenderChart twice, and of course the second time round the TempData has been cleared. A horrible hack to get round this is to reset the TempData["Chart"] back to the MemoryStream that RenderChart has just pulled from TempData but that's deep in the realms of hackery and probably hideously fragile, so I'm going to take the hit on re-reading the data so that it's more robust. – K. Bob Nov 05 '11 at 14:20
  • Have you checked with fiddler what the internet explorer is requesting exactly the second time? – Jan Nov 05 '11 at 18:52
  • Yes - it only does a GET for the IMG (RenderChart) twice not the whole page, and only on a page that POSTs not a GET. There seems to be known problems with IMG tags with an empty 'src'. The two requests happen at almost the same time. I'll build a simple project and see if I can recreate it but TempData seems a bit fragile anyway as anything that would cause an HTTP request will destroy it. – K. Bob Nov 05 '11 at 19:40