Using the GeneratedImage Control in ASP.NET MVC

Published 14 August 10 03:44 AM | Scott Mitchell

One of the free, open-source controls on the ASP.NET team’s CodePlex page is the GeneratedImage control. In a nutshell, the GeneratedImage control is a combination of an ASP.NET Web Control and a set of classes that facilitate programmatically creating, serving, caching, and transforming images. If you store images in the database that need to be served from a web page, if you need to create images on the fly, or if you need to resize, add watermarks, or perform some other image transform, then the GeneratedImage control can help. For more information on the GeneratedImage control and its capabilities, see my articles Dynamically Generating and Caching Images in ASP.NET with the GeneratedImage Control and Image Transforms with the ASP.NET Generated Image Control.

GoogleMaps10Previously, my experience with the GeneratedImage control was in WebForms applications. However, I recently ported my Store Locator ASP.NET application from WinForms to ASP.NET MVC 2 (a two-part article series on porting this application from WinForms to ASP.NET MVC is forthcoming). As the screen shot to the right shows, the store locator results page uses the GeneratedImage control to dynamically create markers for the store locator map, namely a navy circle displaying a white number - 1, 2, 3, and so - to illustrate where on the map a particular store resides.

This image is dynamically generated from an HTTP Handler named NumberToImageHandler.ashx. Specifically, the text to display is passed through the querystring and this HTTP Handler generated and returns the image content. For example, pointing your browser to NumberToImageHandler.ashx?number=1 would create and return the binary content for the 1 image, whereas NumberToImageHandler.ashx?number=2 would create and return the binary content for the 2 image, and so on. This HTTP Handler is a class that extends the Microsoft.Web.ImageHandler class, which is part of the GeneratedImage control library.

For my ASP.NET MVC store locator application I wanted to utilize this existing code, but use a more natural route for accessing the content. Having a .ashx extension just seems so passé. What I wanted instead was to reference these images using routes like:

  • Images/1
  • Images/2
  • ...

Here’s what I ended up doing:

  1. Added a new route in the RegisterRoutes method in Global.asax for the URL pattern Images/{number}.
    routes.Add(
        "ImageRoute",
        new Route(
            "Images/{number}",
            new RouteValueDictionary(),
            new RouteValueDictionary {{ "number", "\\d+" }},
            new NumberRouteHandler()
        )
    );
    Note the constraint that only matches this route if the number parameter is one or more digits. Also note the RouteHandler class that is responsible for handling this route, NumberRouteHandler.
  2. Created the NumberRouteHandler class. This class’s sole responsibility is to return an instance of the HTTP Handler that will handle this request. The code for this class is simple, it just returns an instance of the NumberToImageHandler class:
    public class NumberRouteHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new NumberToImageHandler();
        }
    }
  3. Created the NumberToImageHandler class. This class contains virtually the same code as the NumberToImageHandler.ashx file in the WebForms application. The only difference was instead of reading the number to display from the querystring I read it from the Request object’s RouteData collection. Here’s the line of code that determines which number to display in the image:
    string numberText = HttpContext.Current.Request.RequestContext.RouteData.Values["number"] as string;

With this code in place, anytime a request comes in for Images/1, say, the ASP.NET Routing system dispatches the request to the NumberRouteHandler class, which returns an instance of the NumberToImageHandler class, which reads in the number (1, in this case), dynamically creates the image, and returns it back to the requestor. Pretty slick, eh?

For more information on ASP.NET Routing see URL Routing in ASP.NET 4 and ASP.NET Routing (the technical docs). You can download the ASP.NET MVC version of the store locator from http://www.4guysfromrolla.com/code/GoogleMapsMVC.zip. As noted earlier, there is a two-part article series in the works that walks through porting the store locator from WebForms to ASP.NET MVC and will be published on 4GuysFromRolla.com later this month.

Comments

# Scott Mitchell said on August 17, 2010 04:59 PM:

Here is Part 1 of my two-part series on converting the store locator application from WebForms to ASP.NET MVC:

www.4guysfromrolla.com/.../081810-1.aspx

# Scott Mitchell said on August 20, 2010 12:25 PM:

And here is Part 2 of the series on converting the store locator application from WebForms to ASP.NET MVC:

www.4guysfromrolla.com/.../082510-1.aspx

# Ron DeFreitas said on August 26, 2010 06:32 PM:

What about Caching the images in the client?

# Scott Mitchell said on August 27, 2010 02:56 PM:

Ron, the caching is handled through the GeneratedImage control and doesn't have anything to do with ASP.NET MVC or ASP.NET Routing. For more on the GeneratedImage control's caching capabilities (which can be performed both server-side and client-side), see: www.4guysfromrolla.com/.../042209-1.aspx

# Ryan Smith said on November 17, 2010 01:06 PM:

I'm having trouble finding the Current request context in the GenerateImage method.

Your sample HttpContext.Current.Request.RequestContext seems to fail for me, as RequestContext isn't showing as a valid member of Request.  I'm using MVC 2 and 3.5sp1.

I got it working by manually building one up:

RequestContext context = new RequestContext(new HttpContextWrapper(HttpContext.Current), RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current)));

Ugly as sin but it works.  

# Ryan Smith said on November 17, 2010 01:09 PM:

Also...sorry.  Is there an easy way to open the InfoWindow by clicking on the same icon in the table results?  Right now you can only click on the marker in the window...but I'd like to be able to click on the number in the list too and have it jump to the map and open the window.

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Archives

My Books

  • Teach Yourself ASP.NET 4 in 24 Hours
  • Teach Yourself ASP.NET 3.5 in 24 Hours
  • Teach Yourself ASP.NET 2.0 in 24 Hours
  • ASP.NET Data Web Controls Kick Start
  • ASP.NET: Tips, Tutorials, and Code
  • Designing Active Server Pages
  • Teach Yourself Active Server Pages 3.0 in 21 Days

I am a Microsoft MVP for ASP.NET.

I am an ASPInsider.