How To Serve An Image From An Action And Otherwise Be An MVC Swashbuckler

There comes a time in every pasty young developer’s life when they realize that they must build an application that stores images in a database, and then serves them up via an ASP.NET MVC Action.

Soon after this realization, they have another realization that, unlike with many other shortcuts to brilliance that MVC readily provides, the purveyors of the Web Stack of Love did not serve this one up on a silver platter carried by a pirate riding a unicorn. What they did do (which is twice as pirate, upon reflection) is make their little framework as extensible as the sea is salty. So basically, unless your liver is gilded with lilies, you can sail forth and build your own ruddy ImageResult.

I have one here.

public class ImageResult : ActionResult 
{         
    public Stream ImageStream { get; private set; }         
    public string Extension { get; private set; }         

    public ImageResult(Stream imageStream, string extension)         
    {         
        this.ImageStream = imageStream;         
        this.Extension = extension;         
    }         
        
    public override void ExecuteResult(ControllerContext context)         
    {         
        var response = context.HttpContext.Response;         

        // set the content type based on the extension 
        response.ContentType = string.Format("image/{0}", this.Extension);         

        // copy the image stream to the response output stream 
        this.ImageStream.CopyTo(response.OutputStream);         

        response.End();         
    }         
}

Here’s the consuming code that shows the ImageResult in action:

public ActionResult UserImage(int id)
{
    using (var db = new ApplicationEntities())
    {
        var user = db.Users.Single(p => p.ID == id);
        // read bytes from database into a stream
        var imageStream = new MemoryStream(user.Image);

        // create an image result using the stream
        return new ImageResult(imageStream, "jpeg");
    }
}

See what I did there? In action.

Moving On.

The quick-of-brain among our readership will extrapolate from this that any type of binary file can be served from an Action in this way, with only minor modification to our custom type.

The not-quite-as-quick-of-brain will then reason that this is wicked awesome and that every file should be served this way. To them I will say two things: No, and really this approach should only be used if you need to obtain or manipulate the file in code before serving it. For example, if you need to resize the image, or if access to it is secured in a programmatic way.

So, you know.

Hoist the colors, me hearties.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s