使用ID或操作名称的ASP.NET MVC路由

时间:2022-12-01 08:16:10

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.

我有一个ASP.Net应用程序,它有一个名为'Customers'的区域。该区域有一个名称相同的控制器,只有一个名为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.

这允许我导航到使用以下URL导航到我的Customers控制器上的索引方法。

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).

在我的客户区域,我还有另一个叫做产品的控制器。这有许多方法可以让我使用产品实体(目前主要由Visual Studio自动生成)。

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

使用我当前的路线,我可以使用以下URL链接到产品控制器:

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)

MyDomain / Customers / Products(显示产品控制器的索引页面)MyDomain / Customers / Products / Create(显示添加新产品的页面)。 MyDomain / Customers / Products / Details?id = 1234(显示ID为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:

现在我想要做的是导航到详细信息页面,其中包含更加用户友好的URL,例如:

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)'

参数字典包含方法'System.Web.Mvc.ViewResult Details(Int32)'的非可空类型'System.Int32'的参数'id'的空条目

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.

如果我更改了路由的顺序,那么我可以导航到我的产品控制器上的所有方法,但我的详细信息URL将恢复为具有查询参数的旧格式。

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. 如果我导航到Customers区域,我希望我的URL看起来像'MyDomain / Customers'

  3. If I navigate to the product details page I want my URL to look like "MyDomain/Customers/Products/1234".
  4. 如果我导航到产品详细信息页面,我希望我的URL看起来像“MyDomain / Customers / Products / 1234”。

  5. If I navigate to any other product page I want my URL to look like 'MyDomain/Customers/Products/Create'
  6. 如果我导航到任何其他产品页面,我希望我的网址看起来像'MyDomain / Customers / Products / Create'

4 个解决方案

#1


4  

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

如果ID总是一个int,那么你可以像这样添加一个约束到路由:

context.MapRoute(null,
                 "Customers/Products/{id}",
                 new {controller = "Products", action = "Details", id = UrlParameter.Optional},
                 new {id = @"\d+"} // Constraint to only allow numbers
                );

#2


1  

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:

说明:第一个路由映射到您的详细信息页面,并强制用户提供具有数字格式的ID(第一个MapRoute中的最后一个参数)。如果id没有格式\ d +,它将与路由不匹配,将使用默认值。这将为您提供以下路线:

Customers\Products (index)
Customers\Products\1234 (details of 1234)
Customers\Products\Create (create page for products)
Customers\Products\Edit\1234 (edit page for 1234)

#3


0  

try this

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

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

#4


0  

If you want to keep your existing routes, try doing this:

如果您想保留现有路线,请尝试这样做:

context.MapRoute(null,
     "Customers/Products/{id}", // id is optional, so Customers/Products might reasonably return all products
     new { controller = "Products", action = "Details", id = UrlParameter.Optional },
     new {id = @"\d+"} // must be numeric if present
);

context.MapRoute(null,
     "Customers/Products/{action}/{id}", // Id is optional, so this needs an action.
     new { controller = "Products", action = "Details", id = UrlParameter.Optional }
     // maybe the id is not numeric for all actions? I don't know so I won't constrain it.
);

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

The first two deal with a URL like /Customers/Products/... with one or two other parts and the last one deals with anything else starting with /Customers/

前两个处理像/ Customers / Products / ...这样的URL,带有一个或两个其他部分,最后一个处理以/ Customers /开头的任何其他内容

#1


4  

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

如果ID总是一个int,那么你可以像这样添加一个约束到路由:

context.MapRoute(null,
                 "Customers/Products/{id}",
                 new {controller = "Products", action = "Details", id = UrlParameter.Optional},
                 new {id = @"\d+"} // Constraint to only allow numbers
                );

#2


1  

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:

说明:第一个路由映射到您的详细信息页面,并强制用户提供具有数字格式的ID(第一个MapRoute中的最后一个参数)。如果id没有格式\ d +,它将与路由不匹配,将使用默认值。这将为您提供以下路线:

Customers\Products (index)
Customers\Products\1234 (details of 1234)
Customers\Products\Create (create page for products)
Customers\Products\Edit\1234 (edit page for 1234)

#3


0  

try this

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

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

#4


0  

If you want to keep your existing routes, try doing this:

如果您想保留现有路线,请尝试这样做:

context.MapRoute(null,
     "Customers/Products/{id}", // id is optional, so Customers/Products might reasonably return all products
     new { controller = "Products", action = "Details", id = UrlParameter.Optional },
     new {id = @"\d+"} // must be numeric if present
);

context.MapRoute(null,
     "Customers/Products/{action}/{id}", // Id is optional, so this needs an action.
     new { controller = "Products", action = "Details", id = UrlParameter.Optional }
     // maybe the id is not numeric for all actions? I don't know so I won't constrain it.
);

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

The first two deal with a URL like /Customers/Products/... with one or two other parts and the last one deals with anything else starting with /Customers/

前两个处理像/ Customers / Products / ...这样的URL,带有一个或两个其他部分,最后一个处理以/ Customers /开头的任何其他内容