I tried the solution in the accepted answer above: Using the Canonicalize Pattern url strategy, and then also adding a custom IRouteHandler which then returns a custom IHttpHandler. It mostly worked. Here's one caveat I found:
With the typical {controller}/{action}/{id}
default route, a controller named CatalogController
, and an action method inside it as follows:
ActionResult QuickSelect(string id){ /*do some things, access the 'id' parameter*/ }
I noticed that requests to "/catalog/quick-select/1234" worked perfectly, but requests to /catalog/quick-select?id=1234 were 500'ing because once the action method was called as a result of controller.Execute()
, the id
parameter was null inside of the action method.
I do not know exactly why this is, but the behavior was as if MVC was not looking at the query string for values during model binding. So something about the ProcessRequest
implementation in the accepted answer was screwing up the normal model binding process, or at least the query string value provider.
This is a deal breaker, so I took a look at default MVC IHttpHandler (yay open source!): http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs
I will not pretend that I grok'ed it in its entirety, but clearly, it's doing ALOT more in its implementation of ProcessRequest
than what is going on in the accepted answer.
So, if all we really need to do is strip dashes from our incoming route data so that MVC can find our controllers/actions, why do we need to implement a whole stinking IHttpHandler? We don't! Simply rip out the dashes in the GetHttpHandler
method of DashedRouteHandler
and pass the requestContext
along to the out of the box MvcHandler
so it can do its 252 lines of magic, and your route handler doesn't have to return a second rate IHttpHandler.
tl:dr; - Here's what I did:
public class DashedRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.RouteData.Values["action"] = requestContext.RouteData.GetRequiredString("action").Replace("-", "");
requestContext.RouteData.Values["controller"] = requestContext.RouteData.GetRequiredString("controller").Replace("-", "");
return new MvcHandler(requestContext);
}
}