How do I route images through ASP.NET routing?

2019-03-20 03:39发布

问题:

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?

回答1:

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.



回答2:

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.



回答3:

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 :)



回答4:

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.



回答5:

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.