web 2.0

Goodbye Http Handler, Hello FileResult

If you have been developing applications in ASP.NET MVC then you are probably familiar with the ActionResult class. The ActionResult is the most common type of object returned from an action. When building MVC apps, most of time you will use the ActionResult class.

    Last week while I was working on my open source project WeBlog, I built an HTTP Handler to serve up images. I started using an HTTP Handler for images because I needed a mechanism to prevent bandwidth leeching. The only bad thing about using an HTTP handler for images is that you end up with some pretty ugly URLS. In my case the URL ended up looking like this:

/Image.axd?image=sample.png

Luckily, my friend Ron noticed my new HTTP Handler and mentioned that I could have accomplished the same thing with a controller action that returned a FileResult instead. After a bit of investigation, I realized that Ron was absolutely right. I deleted my HTTP Handler and replaced it with this code, which was added to the Home Controller:

private string GetContentType(string filename) {
    FileInfo file = new FileInfo(filename);            
    switch (file.Extension.ToUpper()) {
        //images
        case ".PNG" : return "image/png";                                
        case ".JPG" : return "image/jpeg";                    
        case ".JPEG": return "image/jpeg";                    
        case ".GIF" : return "image/gif";                    
        case ".BMP" : return "image/bmp";                    
        case ".TIFF": return "image/tiff";
        default:
            throw new NotSupportedException("The Specified File Type Is Not Supported");
    }            
}

public FileResult GetImage(string id) {
    string path = Path.Combine(Engine.GetImageDirectory().FullName, id);            
    return base.File(path, GetContentType( path ) );
}
 

Since this code resides in my Home controller I would need to use the URL like “/Home/GetImage/sample.png” to display an image. Admittedly this URL is still a big ugly, so I decided to use a custom route to clean it up. The new custom route is named “Images” and is mapped it to the Home controller’s GetImage method. Here is the entry used in the global.asax file:

routes.MapRoute("Images",
    "Images/{id}",
    new { controller = "Home", action = "GetImage", id = "" });

Now I can display images by using the following URL:

”/Images/sample.png”

To the end user, this looks like a traditional file path. However, in reality there is no “Images” folder in the root directory. “Images” is just the name of the route being used. In reality, the image files are actually stored in the App_Data/Images folder.

By using a FileResult object with MVC you not only get a pretty URL but you also get a lot of flexibility on where you want your images to reside. You can store images anywhere you want and the URL will never need to change!

Comments

DotNetShoutout , on 3/8/2010 10:17:55 AM Said:

trackback

Goodbye Http Handler, Hello FileResult

Thank you for submitting this cool story - Trackback from DotNetShoutout

DotNetKicks.com , on 3/8/2010 10:18:17 AM Said:

trackback

Goodbye Http Handler, Hello FileResult

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Kelps Brazil, on 3/8/2010 12:14:45 PM Said:

Kelps

I agree with you. File result is awesome, but for old web forms apps I created a library on Codeplex a while ago that do all the heavy lifting resizing images to spare bandwidth. The library is very extensible (I even used it in another project where all the images where stored on the database).

If you can, take a look at : http://cnzkweblibrary.codeplex.com/

Best regards,
Kelps

Al Gonzalez United States, on 3/8/2010 2:20:44 PM Said:

Al Gonzalez

Definitely the way to go. We have custom ActionResults for Images, JSON and Binary content

Greg Roberts United States, on 3/8/2010 11:09:44 PM Said:

Greg Roberts

Just as a heads up there are some minor performance implications by serving up images this way.  You can assume that IIS will serve static content the fastest, then an dedicated httphandler, then your controller being the slowest.  For low traffic site probably not a huge deal, but there is a reason why so many high traffic sites offload static content to multiple domains and CDNs.  You'll also want to make sure you set the caching of the images correctly so that repeat visitors don't keep requesting the files.

hijava's me2DAY , on 3/8/2010 11:20:33 PM Said:

trackback

낭만곰팅의 알림

Goodbye Http Handler, Hello FileResult

iAwaaz-News-for-the-People-by-the-People , on 3/10/2010 12:55:37 AM Said:

trackback

Goodbye Http Handler, Hello FileResult

Thank you for submitting this cool story - Trackback from iAwaaz-News-for-the-People-by-the-People

knowing.net , on 3/15/2010 2:01:10 PM Said:

pingback

Pingback from knowing.net

Knowing .NET  » Blog Archive   » Recent Articles of Interest

Taliesin United States, on 3/19/2010 6:45:25 AM Said:

Taliesin

When serving content dynamically you should support the following partial http header tags:

    * Accept-Ranges
    * Range
    * If-Range

and the following caching http header tags:

    * ETag
    * Expires
    * Last-Modified
    * If-Match
    * If-None-Match
    * If-Modified-Since
    * If-Unmodified-Since
    * Unless-Modified-Since

For an ActionResult that supports this, check out:
code.google.com/.../StaticFileActionResult.cs

Jon United Kingdom, on 3/23/2010 5:32:48 AM Said:

Jon

Why couldn't you just use Url Rewriting to mask the call from /Image.axd?image=sample.png to /Images/sample.png?  You would then get all the performance benefits of an HttpHandler but still have pretty urls.

mikeceranski United States, on 3/23/2010 8:16:31 AM Said:

mikeceranski

Jon, I have never really experimented with URL rewriting but it sounds like it may be a better solution. Thanks for the comment.

Hugo Brazil, on 3/25/2010 4:07:41 PM Said:

Hugo

It's really good, and simple! thanks Michael

Code Capers , on 4/19/2010 12:35:45 AM Said:

trackback

Advice for Aspiring ASP.NET Web Developers

Advice for Aspiring ASP.NET Web Developers

Jaanus Estonia, on 5/4/2010 8:24:15 AM Said:

Jaanus

I'm creating a new platform for my community and I have been experimenting with custom http handlers as well, but you just gave me an even better idea.

24.akemet.com , on 5/20/2010 2:13:04 PM Said:

pingback

Pingback from 24.akemet.com

Optima Aftermarket Spectra Tail Light Kia Sephia, Sephia Replacement Headlight Assembly 2006 Kia Sedona

google tools United States, on 5/30/2010 6:40:00 AM Said:

google tools

I was scared of experimenting with URL rewriting and http custom handlers but you gave me a better solution just before trying. Thanks for making me out of the possible difficulties just before i entered into it.

Comments are closed