8

I would like to specify my routing tables such that they would feel much more "natural"

/Products
/Product/17
/Product/Edit/17
/Product/Create

Close to the defaults configuration but such that "Index" action would be mapped to the multiples form of the controller name and "Details" action would be mapped directly with an id of the item directly following the controller name.

I know I can achieve this by explicitly defining special routing mappings like this:

routes.MapRoute(
    "ProductsList",
    "Products",
    new { controller = "Product", action = "Index" }
);
routes.MapRoute(
    "ProductDetails",
    "Product/{id}",
    new { controller = "Product", action = "Details" }
);

/*
 * Ditto for all other controllers
 */

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

The code above is way too verbose for my tastes and has the downside that each controller needs to be mentioned at least twice to prevasively apply this url pattern.

Is there some way to generalize this or am I bound to manual labour in this case?

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Roland Tepp
  • 8,301
  • 11
  • 55
  • 73
  • Why use `Products` and `Product` instead of choosing one ? Check out http://mvccoderouting.codeplex.com/ if you want to completely forget about routing issues. – Max Toro Mar 04 '11 at 21:18
  • 1
    because ´Products´ is a listing of multiple products, thus it makes sort of sense to refer to products in plural rather than singular form. On the other hand, when I refer to a single product, I usually use singular form that is why I want the referring url also use singular form. – Roland Tepp Mar 10 '11 at 16:48

1 Answers1

2

You can try something like this:

routes.MapRoute(
                "ProductsList",
                "{pluralizedControllerName}",
                new { controller = "Home", action = "Index" },
                new { pluralizedControllerName = new PluralConstraint() }
                );

            routes.MapRoute(
                "ProductDetails",
                "{controller}/{id}",
                new { controller = "Home", action = "Details" },
                new { id = @"\d+" }
            );

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

Notice the constraint in second route, it ensures that /Product/Create doesn't get picked by second route so that it gets mapped as third.

For route testing you can use routedebugger, and for writing unit test for routes try MvcContrib-TestHelper. You can get both with NuGet.

EDIT:

You can use this simple pluralizer and then implement something like this:

public class PluralConstraint : IRouteConstraint
    {
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            List<string> names = GetControllerNames();//get all controller names from executing assembly
            names.ForEach(n => n.Pluralize(n));
            return names.Contains(values[parameterName]);
        }
    }
frennky
  • 12,581
  • 10
  • 47
  • 63
  • Not quite what I asked for. The base of my question was, how can I define route mapping to the "Index" action of any controller to the url with controller's name in multiple form. EX: Let's say I have a controller called _ProductController_. In this case I want to set up my routing such that requests to `/Products` (notice the multiple form) would call the _ProductController.Index()_. And I really want it to be defined in such a way that I don't have to re-define it for every controller in the MVC app – Roland Tepp Feb 17 '11 at 08:09
  • Sorry, now I understand want you need. You want Index route to be in plural. I've updated my answer, let me know if it helps. – frennky Feb 17 '11 at 11:27
  • Nice, thanks - from the looks of it, this seems to be exactly what I wanted. I'll try it out and let you know – Roland Tepp Feb 25 '11 at 15:51
  • @RolandTepp Are you OK? – Joel McBeth Apr 13 '14 at 20:39