2

I'm using ASP.Net with MVC 3 and trying to auto generate images. In my view I am probably going to generate anything from 1 to a 50 images (maybe more eventually) which are currently one shot throw away images. This is because they show the current results of my data, which gets updated fairly frequently and so the generated images can't be relied on for very long.

Currently I am graphing results on the fly. Users can select which results to view and how then I get the results, write the graphs to file then pick up the filenames and display them in my view, but this is not working out so well and as I do not re-use the images I would just prefer to not bother storing them at all.

So far my solution is based on the following idea Can an ASP.NET MVC controller return an Image?.

In my controller I have:

public ActionResult GetImage(GraphData GraphData)
    {
        Response.ContentType = "image/png";
        using (var ms = new MemoryStream())
        {
            var chart = GraphService.GetChart(GraphData.ResponseItems,GraphData.QuestionDisplaySetup,GraphData.QuestionCutOffs,250,250);
            chart.SaveImage(ms, ChartImageFormat.Png);
            ms.Seek(0, SeekOrigin.Begin);

            return File(ms.ToArray(), "image/png");
        }

    }

and then in the .cshtml file:

foreach (var item in @Model.GraphDataList)
{
    <img src="@Url.Action("GetImage", "Download", new { GraphData = item})" alt="" /> 
}

and a model:

public class GraphData
{        
    public IEnumerable<ResultItem> ResultItems { get; set; }
    public ResultDisplaySetup ResultDisplaySetup { get; set; }
    public IEnumerable<ResultCutOff> ResultCutOffs { get; set; }
}

but as you probably have guessed by the question this does not work.

If I do the following in my .cshtml/view:

Html.RenderAction("GetImage", "Download", new { GraphData = filename });

Then I pickup the object in my controller action without any problems, however I can't use that in the img tag and ASP.NET MVC null model passed to controller action tells me @Url.Action can't send a complex objects.

I fell down a rabbit whole of trying to generate the serialized objects myself and write my own url builder using RouteValueDictionary and tagbuilder, which is probably possible. An example is: Passing an object to HTML attributes

but this example is just too simple and obviously so I am as I couldn't quite get the thing working.

I have the added complication that likely the Html.RenderAction will not work on the published website because it is not at the root of the website (e.g. /whatever/MyWebSite) this is for security purposes and would be too difficult to change right now.

Anyway it seems like I am working against the framework instead of with it. Any ideas anyone?

Thanks!

Community
  • 1
  • 1
user419636
  • 25
  • 4
  • What would you want the URL to look like? – SLaks Oct 31 '11 at 17:48
  • If you are using GDI+ to draw the image though on the server you could think about transitioning to drawing it on the client in HTML 5 natively if thats an option. – Paul Tyng Oct 31 '11 at 18:11

1 Answers1

2

It is not a good idea to pass complex objects in a URL.

Instead, store them in the session, pass an identifier for the object in the session in the URL, and read it from the session in the action.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Unless you can transition the building of the model almost entirely to GetImage this is the best way to handle it. There are some hacky solutions like using [CSS inline images](http://www.websiteoptimization.com/speed/tweak/inline-images/) or [Canvas images using putImageData](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-putimagedata) where the data for the image can be sent in the page itself, but I wouldn't recommend those. – Paul Tyng Oct 31 '11 at 18:10
  • Session["someidfortheimage"] = GraphData object in my view and changeing the action to public ActionResult GetImage(string id) GraphData GraphData = Session[id]; worked a treat! Thanks! – user419636 Nov 01 '11 at 13:10