So I was thinking tonight, what if I want my MVC application to serve images that are stored in a SQL database as binary data? Or files that are stored in the database? One of the things that I really like about MVC is that ability to add custom functionality in a fairly simple way. A few days ago, I wrote a post showing how to implement a custom HtmlHelper method for rendering a group of checkboxes. In this post, we are going to create a custom ActionResult class that can serve an image as the return value from a controller action method.
In the typical controller action method, a View is returned. This allows the controller to render the View as the response for the web request. You are probably familiar with this if you have been using MVC. Here is a common example of this:
So to answer our initial question, let's create an ImageResult class that will write the bytes of an image to the web response. The code below is fairly straightforward - we inherit from ActionResult, define some properties that we need, set the properties in the constructor, and then create and return the response.
The next thing that I did was create a set of extension methods for the Controller class. All that these methods do is create and return a new instance of the ImageResult class based on the arguments. This allows you to pass the image as either a stream or a byte array.
Now that we have that done, let's create a controller action method to get the images. We just need to specify the binary image data and the content type for the image.
And we are done, and it was pretty easy. In just a few dozen lines of code, we have provided a way to return images from a controller action without the need to create a view. The result looks are shown below (and notice how we can user a meaningful URL, rather than something like "GetFile.aspx?filename=netLogo.jpg"):
We could do the same thing to return files from a database server by creating a FileResult class that is similar to ImageResult. In fact, the only difference needed is to change the content type to "application/octet-stream" and then the browser will prompt the user for where to save the file.