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();
}
}
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;
}
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.
Try defining the optional string dynamicRoute parameter on your route:
routes.MapRoute(
"CatchAll",
"{*dynamicRoute}",
new { controller = "CatchAll", action = "ChoosePage", dynamicRoute = UrlParameter.Optional } );
来源:https://stackoverflow.com/questions/16527740/mvc-4-catch-all-route-never-reached