How do I route images through ASP.NET routing?
Asked Answered
C

5

7

I'd like to create a dynamic thumbnail resizer so that you can use the following URL to get a resized image:

http://server/images/image.jpg?width=320&height=240

I tried setting up a route like this:

routes.MapRoute(null,
                "{filename}",
                new { controller = "Image", action = "Resize" });

But if the file exists at the URL, ASP.NET will bypass the routing and return you just the file instead. How do I force ASP.NET to route the images instead of returning what's on disk?

Canaanite answered 18/12, 2010 at 1:50 Comment(6)
If you provide a resizer like that watch out for potential DOS. E.g. if I request image.jpg?width=100000&height=100000 your server will be in trouble.Fries
Thanks for the advice. I've already accounted for simple DOS attacks like that.Canaanite
Seems like i was a bit too fast on the trigger there. There seems to be a property you can set which allows you to enforce a route even for existing files. See my updated answer.Peag
btw, please don't call it MVC routing... routing is a first class citizen in asp.net and works for both Webforms and MVC just the same.Peag
besides all good responses, I would recommend caching the generated thumbnail plus allowing a small predefined set of sizes.Darsie
#2532968Hillyer
R
3

Thats how asp.net routing works, there is no away around that... you have to use Rewrite if you want to intercept requests for existing files.

Update

Seems like i was a bit too fast on the trigger there. There seems to be a property you can set which allows you to enforce a route even for existing files.

RouteCollection.RouteExistingFiles Property

http://msdn.microsoft.com/en-us/library/system.web.routing.routecollection.routeexistingfiles.aspx

Gets or sets a value that indicates whether ASP.NET routing should handle URLs that match an existing file. True if ASP.NET routing handles all requests, even those that match an existing file; otherwise, false. The default value is false.

Revolver answered 18/12, 2010 at 2:1 Comment(0)
P
4

Why not just use an action to do this? A controller's action can stream back an image. Otherwise, the typical way, say with ASPX, is that a handler or handler factory listens for the file extension and processes it accordingly. Or use URL rewriting to rewrite the URL in the request.

Prejudge answered 18/12, 2010 at 2:2 Comment(1)
I think you misunderstood my original question. I already created the action, now I'm trying to get MVC to route to it.Canaanite
R
3

Thats how asp.net routing works, there is no away around that... you have to use Rewrite if you want to intercept requests for existing files.

Update

Seems like i was a bit too fast on the trigger there. There seems to be a property you can set which allows you to enforce a route even for existing files.

RouteCollection.RouteExistingFiles Property

http://msdn.microsoft.com/en-us/library/system.web.routing.routecollection.routeexistingfiles.aspx

Gets or sets a value that indicates whether ASP.NET routing should handle URLs that match an existing file. True if ASP.NET routing handles all requests, even those that match an existing file; otherwise, false. The default value is false.

Revolver answered 18/12, 2010 at 2:1 Comment(0)
S
2

You could also consider:

  1. Writing a Module to handle these image routes before it hits routing (registered in Web.Config)
  2. Write your own route handler specifically to handle these images.

Both would allow you to remove the need to write as a controller, I think this is cleaner.

Very basic example of your own route handler (from memory)...

Register as a normal route:

/* Register in routing */
routes.Add("MyImageHandler",
           new Route("my-custom-url/{folder}/{filename}", 
           new ImageRouteHandler())
);


/* Your route handler */
public class ImageRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        string filename = requestContext.RouteData.Values["filename"] as string;
        string folder = requestContext.RouteData.Values["folder"] as string;
        string width = requestContext.HttpContext.Request.Params["w"] as string;
        string height = requestContext.HttpContext.Request.Params["h"] as string;

        // Look up the file and handle and return, etc...
    }
}

Hope these help. Lots of ways to extend and achieve :)

Sos answered 22/2, 2012 at 10:3 Comment(0)
W
1

The simplest way would be to route all images through the controller and store your images in a separate location

routes.MapRoute("Images",
            "/images/{filename}",
            new { controller = "Image", action = "Resize" });

/sitebase/images/image.jpg         //public image location
/sitebase/content/images/image.jpg //real image location

Your controller would then see which image was being requested and load the appropriate file from the file system. This would allow you to do what you want without any special handling.

Weakfish answered 18/12, 2010 at 5:49 Comment(0)
M
0

How about:

routes.MapRoute("Images",
        "/images/{filename}.jpg",
        new { controller = "Image", action = "Resize" });

That Should ensure that only URLs with .jpg as an extension get matched to that route and get routed appropriately.

Also remember you want to add your actions in order of most specific to least specific, with your default one being added last.

Of course, your action still needs to serve up the Image using a filecontentresult.

Murder answered 2/7, 2011 at 13:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.