views:

558

answers:

4

Is there an easy way to get the MvcRouteHandler to convert all hyphens in the action and controller sections of an incoming URL to underscores as hyphens are not supported in method or class names.

This would be so that I could support such structures as sample.com/test-page/edit-details mapping to Action edit_details and Controller test_pagecontroller while continuing to use MapRoute method.

I understand I can specify an action name attribute and support hyphens in controller names which out manually adding routes to achieve this however I am looking for an automated way so save errors when adding new controllers and actions.

A: 

Don't know of a way without writing a map for each url:

routes.MapRoute("EditDetails", "test-page/edit-details/{id}", new { controller = "test_page", action = "edit_details" });
zaph0d
This is what I meant by "manually adding routes" and what I am trying to avoid.
John
+1  A: 

You could take a look at this article showing how to implement a custom MvcRouteHandler.

Darin Dimitrov
Useful thank you.
John
+4  A: 

I have worked out a solution. The requestContext inside the MvcRouteHandler contains the values for the controller and action on which you can do a simple replace on.

Public Class HyphenatedRouteHandler
    Inherits MvcRouteHandler

    Protected Overrides Function GetHttpHandler(ByVal requestContext As System.Web.Routing.RequestContext) As System.Web.IHttpHandler
        requestContext.RouteData.Values("controller") = requestContext.RouteData.Values("controller").ToString.Replace("-", "_")
        requestContext.RouteData.Values("action") = requestContext.RouteData.Values("action").ToString.Replace("-", "_")
        Return MyBase.GetHttpHandler(requestContext)
    End Function

End Class

Then all you need to replace the routes.MapRoute with an equivalent routes.Add specifying the the new route handler. This is required as the MapRoute does not allow you to specify a custom route handler.

routes.Add(New Route("{controller}/{action}/{id}", New RouteValueDictionary(New With {.controller = "Home", .action = "Index", .id = ""}), New HyphenatedRouteHandler()))
John
+4  A: 

C# version of John's Post for anyone who would prefer it: C# and VB version on my blog

public class HyphenatedRouteHandler : MvcRouteHandler{
        protected override IHttpHandler  GetHttpHandler(RequestContext requestContext)
        {
            requestContext.RouteData.Values["controller"] = requestContext.RouteData.Values["controller"].ToString().Replace("-", "_");
            requestContext.RouteData.Values["action"] = requestContext.RouteData.Values["action"].ToString().Replace("-", "_");
            return base.GetHttpHandler(requestContext);
        }
    }

...and the new route:

routes.Add(
            new Route("{controller}/{action}/{id}", 
                new RouteValueDictionary(
                    new { controller = "Default", action = "Index", id = "" }),
                    new HyphenatedRouteHandler())
        );

You can use the following method too but bear in mind you would need to name the view My-Action which can be annoying if you like letting visual studio auto generate your view files.

[ActionName("My-Action")]
public ActionResult MyAction() {
    return View();
}
Andi
This worked great... however watch out for `controller = "Default"`. I got a 404 a couple times before noticing that and changing it to "Home".
Jon Freeland