Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 4 catch all route never reached

When attempting to create a catch all route in MVC 4 (something I've found several examples of, and based my code on) it returns a 404 error. I'm running this on IIS 7.5. This seems like a straight forward solution, so what am I missing?

One note, if I move the "CatchAll" route above the "Default" route it works. But of course then none of the other controllers are ever reached.

Here is the code:

Route.Config:

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

        routes.MapRoute(
            "CatchAll",
            "{*dynamicRoute}",
            new { controller = "CatchAll", action = "ChoosePage" }
        );

Controller:

public class CatchAllController : Controller
{

    public ActionResult ChoosePage(string dynamicRoute)
    {
        ViewBag.Path = dynamicRoute;
        return View();
    }

}
like image 693
gsxrboy73 Avatar asked May 13 '13 17:05

gsxrboy73


2 Answers

Since the ultimate goal of creating the catchall route was to be able to handle dynamic urls and I was unable to find a direct answer to the original issue above, I approached my research from a different perspective. In doing so I came across this blog post: Custom 404 when no route matches

This solution allows handling of multiple sections within a given url (i.e. www.mysite.com/this/is/a/dynamic/route)

Here is the final custom controller code:

public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
 {
     if (requestContext == null)
     {
         throw new ArgumentNullException("requestContext");
     }

     if (String.IsNullOrEmpty(controllerName))
     {
         throw new ArgumentException("MissingControllerName");
     }

     var controllerType = GetControllerType(requestContext, controllerName);

     // This is where a 404 is normally returned
     // Replaced with route to catchall controller
     if (controllerType == null)
     {
        // Build the dynamic route variable with all segments
        var dynamicRoute = string.Join("/", requestContext.RouteData.Values.Values);

        // Route to the Catchall controller
        controllerName = "CatchAll";
        controllerType = GetControllerType(requestContext, controllerName);
        requestContext.RouteData.Values["Controller"] = controllerName;
        requestContext.RouteData.Values["action"] = "ChoosePage";
        requestContext.RouteData.Values["dynamicRoute"] = dynamicRoute;
     }

     IController controller = GetControllerInstance(requestContext, controllerType);
     return controller;
 }
like image 68
gsxrboy73 Avatar answered Nov 13 '22 06:11

gsxrboy73


It's probably because whatever route your're testing this with is matching your 1st - Default route. The way the routing in MVC works, any address you pass in will try to match routes in your routes collection in order of appearance. Once it find the 1st matching route it aborts further execution. In this case your Default route is 1st one in the list so if it is matched your second route will never be examined.

Basically write something like http://www.mysite.com/Home/Testing/Item/Page in your address bar and this should fail to match to your Default route and then try to match the CatchAll route.

like image 29
Marko Avatar answered Nov 13 '22 05:11

Marko