1
        //standard routing
        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", 
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
        );

        //the custom route I added
        routes.Add(
           new Route("Fish/Image",

               new ImageHandlerRouteHandler()
           )
        );

I thought this would use my ImageHandlerRouteHandler but all I get at Fish/Image is a 404.

Tom
  • 7,994
  • 8
  • 45
  • 62

3 Answers3

7

Add the route before the default route.

routes.Add(
           new Route("Fish/Image",

               new ImageHandlerRouteHandler()
           )
        );

//standard routing
        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", 
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
        );

The request is mapped to the first matching route in routes table. Since default route have no restrictions, it gets called before your custom route.

Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156
  • Thankyou, this was actually how I had it before. But then I moved it to after the standard one because it was affecting the default routing. e.g. Html.ActionLink was producing urls like this: Fish/Image?action=Register&controller=Account So the question now becomes - why? and how to avoid this? – Tom Oct 14 '11 at 11:57
  • How do you call Html.ActionLink() ? – Ufuk Hacıoğulları Oct 14 '11 at 12:02
  • `Html.ActionLink("Register", "Register")` produces the url above – Tom Oct 14 '11 at 12:05
  • You should use URL.Action() if you are displaying images and provide tags. – Ufuk Hacıoğulları Oct 14 '11 at 12:05
  • I don't understand, are you saying I shouldn't use Html.ActionLink? – Tom Oct 14 '11 at 12:12
  • The issue is described in detail here but the solution is... 'nasty' http://stackoverflow.com/questions/4351415/custom-iroutehandler-route-screws-up-mvc-link-building – Tom Oct 14 '11 at 12:16
  • You are not providing a route name. Take a look at counsellorben's answer. – Ufuk Hacıoğulları Oct 14 '11 at 12:24
3

When you have the Fish/Image route before the default route, the problem you will have in MVC building links is that the Fish/Image route appears to satisfy ALL requests. In order to have this route work, change it as follows:

routes.Add(
    "FishImage",
    new Route(
        "{controller}/Image", 
        new RouteValueDictionary(new { controller = "Fish" }),
        new RouteValueDictionary(new { controller = @"^(?!fish).+"  }),
        null,
        new ImageHandlerRouteHandler() 
    ) 
);

This changes the route, so that on the link building side, your other links will fail this route. Currently, MVC sees that it can build any link to match this route, so it does. With the constrained route, MVC will now see that other links will fail this route.

counsellorben
  • 10,924
  • 3
  • 40
  • 38
1

The order that routes appear are important. Add your route first and left the Default as a fall back.

GRGodoi
  • 1,946
  • 2
  • 24
  • 38
  • Thanks. When I tried this, I encountered another problem, see my comment on Ufuk's answer. – Tom Oct 14 '11 at 11:59