Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC Routing using ID or action name

I have an ASP.Net application which has an area called 'Customers'. This area has a controller with the same name with a single method called Index.

I have the following route defined:

context.MapRoute(null,
    "Customers/{controller}/{action}",
    new { controller = "customers", action = "Index" }
);

This allows my to navigate to use the following URL to navigate to the index method on my Customers controller.

MyDomain/Customers

In my customer area I also have another controller called products. This has a number of methods that allow me to work with product entities (mostly auto-generated by Visual Studio at the moment).

With my current route I can navigate to the products controller using URL's like this:

MyDomain/Customers/Products (shows the index page of the products controller) MyDomain/Customers/Products/Create (Shows a page to add new products). MyDomain/Customers/Products/Details?id=1234 (Show the product with the id of 1234)

Now what I want to be able to do is navigate to the details page with a much more user friendly URL such as:

MyDomain/Customers/Products/1234

I have defined a new route that look like this:

context.MapRoute(null,
    "Customers/Products/{id}",
    new { controller = "Products", action = "Details" }
    );

The route is defined before the first route I demonstrated. This allows me to navigate to the products page as I want, however I can no longer navigate to other methods on my products controller.

E.G. The following URL

MyDomain/Customers/Products/Create

Gives me the following error:

The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ViewResult Details(Int32)'

If I change the order of the routes then I can navigate to all the methods on my products controller but my details URL reverts to the old format of having a query parameter.

If I update the route to look like this:

context.MapRoute(null,
    "Customers/Products/{id}",
    new { controller = "Products", action = "Details", id = UrlParameter.Optional }
    );

Then I still get the same problem.

Can anyone tell me how to structure my routes to get the result I want? In summary:

  1. If I navigate to the Customers area I want my URL to look like 'MyDomain/Customers'
  2. If I navigate to the product details page I want my URL to look like "MyDomain/Customers/Products/1234".
  3. If I navigate to any other product page I want my URL to look like 'MyDomain/Customers/Products/Create'
like image 481
Benjamin Gale Avatar asked Aug 22 '12 09:08

Benjamin Gale


People also ask

How can use routing in ASP.NET MVC?

Routing in ASP.NET MVC cs file in App_Start Folder, You can define Routes in that file, By default route is: Home controller - Index Method. routes. MapRoute has attributes like name, url and defaults like controller name, action and id (optional).

Which is the correct default route mapping within MVC?

The Default route maps the first segment of a URL to a controller name, the second segment of a URL to a controller action, and the third segment to a parameter named id. The Default route maps this URL to the following parameters: controller = Home. action = Index.

What is the use of action name in MVC?

ActionName attribute is an action selector which is used for a different name of the action method. We use ActionName attribute when we want that action method to be called with a different name instead of the actual name of the method.

Can we have two action methods with same name in MVC?

While ASP.NET MVC will allow you to have two actions with the same name, . NET won't allow you to have two methods with the same signature - i.e. the same name and parameters. You will need to name the methods differently use the ActionName attribute to tell ASP.NET MVC that they're actually the same action.


2 Answers

If the ID is always going to be an int then you can add a constraint to the route like this:

context.MapRoute(null,
                 "Customers/Products/{id}",
                 new {controller = "Products", action = "Details", id = UrlParameter.Optional},
                 new {id = @"\d+"} // Constraint to only allow numbers
                );
like image 168
Richard Dalton Avatar answered Sep 28 '22 03:09

Richard Dalton


Try something like this:

public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
        "Products_Details",
        "Customers/Products/{id}",
        new { controller="Products", action="Details" },
        new { id = @"\d+" }
    );

    context.MapRoute(
        "Customers_default",
        "Customers/{controller}/{action}/{id}",
        new { action = "Index", id = UrlParameter.Optional }
    );
}

Update: added constraint on route.

Explanation: The first route maps to your details page and forces the user to provide an id that has the format of numbers (the last parameter in the first MapRoute). If the id doesn't have the format \d+ it will not match the route and the default will be used. This will give you the following routes:

Customers\Products (index)
Customers\Products\1234 (details of 1234)
Customers\Products\Create (create page for products)
Customers\Products\Edit\1234 (edit page for 1234)
like image 32
Tomas Jansson Avatar answered Sep 28 '22 03:09

Tomas Jansson