Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Prevent Multiple ASP.NET MVC Route Mappings

I have an ASP.NET MVC routing question. First, let me explain my areas setup. It's quite simple.

Areas
|
+--Foo
   |
   +--Controllers
      |
      +--BarController.cs

I have a folder in my areas called "Foo" and controller called "BarController.cs" The Bar controller has several methods named "DoStuff1()", "DoStuff2()", etc.

My website uses the following URLs:

/foo/bar/15
/foo/bar/dostuff1
/foo/bar/dostuff2

The first URL requires an id and uses the default Index() method in the Bar controller to populate the webpage with a view and model.

In the second and third URLs, I'm using them for jQuery ajax calls.

Here is the code from my area registrion

context.MapRoute(null, "Foo/Bar/DoStuff1", new
{
    action = "DoStuff1",
    controller = "Bar"
});

context.MapRoute(null, "Foo/Bar/DoStuff2", new
{
    action = "DoStuff2",
    controller = "Bar"
});

context.MapRoute(null, "Foo/Bar/{id}", new
{
    action = "Index",
    controller = "Bar"
});

My problem is that for each new controller method I create, I have to add another route mapping in the area registrion file. For example, if I add the method DoStuff3(), I'll need to add this to the area registration:

context.MapRoute(null, "Foo/Bar/DoStuff3", new
{
    action = "DoStuff3",
    controller = "Bar"
});

How can I create a generic route mapping to handle the URLs I mentioned above that doesn't require new additions to the area registration file for new controller methods?

like image 270
Halcyon Avatar asked Feb 14 '13 18:02

Halcyon


1 Answers

You can pull out the controller action.

Write the URL like this:

"Foo/Bar/{action}"

Additionally, you can pull out the controller as well, and write

"Foo/{controller}/{action}"

In this case, action = "Index" provides a default value of "Index" if no action parameter is provided.

In this case, you need to disambiguate between "Foo/Bar/{action}" and "Foo/Bar/{id}". Since matching is done in order, you'll want to put the id route first, and add a numeric constraint to the id parameter. This allows valid numeric ids to match it, and action names to skip down to the next route. Your two routes would look like this:

context.MapRoute(null, "Foo/Bar/{id}", new
{
    action = "Index",
    controller = "Bar"
},
new { id = @"\d+" });

context.MapRoute(null, "Foo/Bar/{action}", new
{
    action = "Index", //optional default parameter, makes the route fall back to Index if no action is provided
    controller = "Bar"
});
like image 130
yoozer8 Avatar answered Oct 25 '22 13:10

yoozer8