Returning Thumbnails With the MVC Framework

In my last post, we put together a quick and simple photo gallery. This post will be building on that.

Depending on the size of your photo, however, it didn’t have the worlds greatest user experience. I’ll be playing with the CSS, JavaScript and a ton more over time. Today, however, I’m going to be just returning a thumbnail rather than the full picture to show in the view.

I don’t want to have to physically create each of the thumbnails so we’ll generate those dynamically on the fly.

Creating a Custom ActionResult

To return a given type of result, you have to return an ActionResult of that type. The types that are currently built in are View, Redirect, RedirectToAction, RedirectToRoute, Content, or Json. We need to create a specific action type that we’ll call the ThumbnailResult. It will be created with a virtual path to the picture that we need to show. When it’s executed, it will generate and return the thumbnail.

public class ThumbnailResult : ActionResult
{
    public ThumbnailResult(string virtualPath)
    {
        this.VirtualPath = virtualPath;
    }

    public string VirtualPath {get;set;}

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = "image/bmp";

        string fullFileName =
            context.HttpContext.Server.MapPath("~/images/" + VirtualPath);
        using (System.Drawing.Image photoImg =
            System.Drawing.Image.FromFile(fullFileName))
        {
            using (System.Drawing.Image thumbPhoto =
                photoImg.GetThumbnailImage(100, 100, null, new System.IntPtr()))
            {
                using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                {
                    thumbPhoto.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                    context.HttpContext.Response.BinaryWrite(ms.ToArray());
                    context.HttpContext.Response.End();
                }
            }
        }
    }
}

Notice that we’ve set the HttpContext.Response.ContentType to “image/bmp”. This is critical for the browser to understand the data that it recieves.

Leveraging the Custom ActionResult

The next step is to add a method to the controller that will return the ThumbnailResult.

public ActionResult Thumbnail(string id)
{
    return new ThumbnailResult(id);
}

And lastly we need to update the view to leverage this new thumbnail action.

<a href=”/images/<%= image.Path %>“><img src=”/image/thumbnail/<%= image.Path %>” /></a>

When you run now, you should get the thumbnails instead of the full sized picture. However, you should still be able to click through to the actual picture. In an upcoming blogpost, we’ll change this to use lightbox.js.