11

Question

How can I dynamically resize an image in ASP.NET MVC?

Background

I'm trying to automatically create thumbnails from images that are already on the server. In ASP.NET Webforms, I created a HTTPHandler to do this and added verbs in the web.config for all image extensions to pass through the handler. The handler was nice in that if you wanted the original image, you'd use a typical image tag:

<img src="pic.jpg"/>

But if you wanted a resized image, you'd use:

<img src="pic.jpg?width=320&height=240"/>

Is there a way to duplicate the same behavior in ASP.NET MVC?

3
  • 3
    Unlike an HttpHandler, a HttpModule will work seamlessly with both MVC and WebForms. The most popular image resizing HttpModule for ASP.NET is imageresizing.net . It's free, open-source, and foolproof. Commented Jun 22, 2011 at 23:34
  • Cool, thanks. Unfortunately, imageresizing.net wasn't around in 2009 when I asked the question. Commented Apr 26, 2012 at 21:09
  • It was, actually. Been around since 2007. But in all fairness, it didn't get to page 1 of google till early 2009... Commented Apr 26, 2012 at 21:38

3 Answers 3

13

Using WebImage class that comes in System.Web.Helpers.WebImage you can achieve this.

You can use this great kid to output resized images on the fly.

Sample code:

public void GetPhotoThumbnail(int realtyId, int width, int height)
{
    // Loading photos’ info from database for specific Realty...
    var photos = DocumentSession.Query<File>().Where(f => f.RealtyId == realtyId);

    if (photos.Any())
    {
        var photo = photos.First();

        new WebImage(photo.Path)
            .Resize(width, height, false, true) // Resizing the image to 100x100 px on the fly...
            .Crop(1, 1) // Cropping it to remove 1px border at top and left sides (bug in WebImage)
            .Write();
    }

    // Loading a default photo for realties that don't have a Photo
        new WebImage(HostingEnvironment.MapPath(@"~/Content/images/no-photo100x100.png")).Write();
}

In a view you'd have something like this:

<img src="@Url.Action("GetPhotoThumbnail",
     new { realtyId = item.Id, width = 100, height = 100 })" />

More about it here: Resize image on the fly with ASP.NET MVC

There's also a great tutorial on the ASP.NET site: Working with Images in an ASP.NET Web Pages (Razor) Site.

Sign up to request clarification or add additional context in comments.

Comments

3

You can definitely reuse the same IHttpHandler. You just need a new IRouteHandler to map the incoming request to the correct handler:

public class ImageRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new YourImageHttphandler();
    }
}

In your routes, add:

routes.Add("Images", new Route("images/{*file}", new ImageRouteHandler()));

Now any request in /images (e.g. /images/pic.jpg?width=320&height=240) will be handled by your existing handler. Obviously you can change the route pattern to match any path that makes sense, just like a typical MVC route.

5 Comments

Will this code work for subdirectories under the images folder?
@DanielT yes! See the tiny edit to my answer - adding the asterisk to {*file} will have that route catch everything under /images, including subdirectories.
Hmm, slight problem: this routing only works if I manually type the URL into the address bar, like so: http://localhost:4692/Content/images/IMG_0146.JPG. However, I need to embed the image inside a View, and it doesn't go through the routing handler since it's already been routed to the controller.
@DanielT hmm, not sure what you mean. Each resource on the page, such as <img src..., is sent to the server by the browser as a distinct request, and each will be handled separately. Can you describe what you're seeing in more detail?
What about images that are in CSS as background images?
0

You can do the same in mvc. You can either use a httphandler as you did before or you create an action that streams the resized image.

If it were me I would create a controller with a resize method.

6 Comments

Can you elaborate on what you said about creating an action that streams the resized image?
Wait, I think I get it. You mean to use RedirectToAction("Thumbnail") that returns a thumbnail, right?
I'm not at my computer, but there is a "Content" method that streams data. I believe it has a signature that takes a stream or byte array and then has a paramenter for content type. For the content type you would pass "image/jpg." Then all you need is to reference the action in an HTML image element.
The above assumes you already have the resized the image in memory as a stream oy byte[]
I'd very much prefer the view to resize the image. My opinion is that the controller should only give the view a 'table' of data to display, in this case, a list of all the images that match a criteria, and it's the view's job to handle the image resizing, if necessary.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.