英文:
Url routing getting confused between 2 routing rules
问题
以下是代码部分的翻译:
我有两个类似的网站路由规则。一个用于类别,另一个用于品牌
app.MapControllerRoute(
name: "CategoryPage",
pattern: "shop/{controller}/{id}/{pageNumber}/{pageSize}/{*categoryName}",
defaults: new { area = "shop", controller = "category", action = "index" });
app.MapControllerRoute(
name: "BrandPage",
pattern: "shop/{controller}/{id}/{pageNumber}/{pageSize}/{*brandName}",
defaults: new { area = "shop", controller = "brand", action = "index" });
不同之处仅在于控制器和品牌/类别名称。
我的网址应该如下所示。
shop/Category/79/1/80/Clothing-Accessories
shop/Brand/79/1/80/my-brand
但是,我的路由规则列表中的第二个总是显示为
shop/Brand/159/1/80?brandName=Anchor-Crew
我以为使用不同的控制器名称可以告诉它使用哪一个,但似乎并非如此。一个可能的解决方案是给它们都类似的名称,如'slug'。
更新以包括控制器
public async Task<IActionResult> Index([FromRoute] long id, int pageNumber, int pageSize, string brandName)
{
PaginatedList<Product> products = GetProducts(id, pageNumber, pageSize);
Brand brand = await _brandService.GetAsync(id);
}
public async Task<IActionResult> Index([FromRoute] long id, int pageNumber, int pageSize, string categoryName)
{
Category? category = await _categoryService.Get(id, true);
}
英文:
I have two similar routing rules for my website. One for categories and another for brands
app.MapControllerRoute(
name: "CategoryPage",
pattern: "shop/{controller}/{id}/{pageNumber}/{pageSize}/{*categoryName}",
defaults: new { area = "shop", controller = "category", action = "index" });
app.MapControllerRoute(
name: "BrandPage",
pattern: "shop/{controller}/{id}/{pageNumber}/{pageSize}/{*brandName}",
defaults: new { area = "shop", controller = "brand", action = "index" });
All that is different is the controller and the brand / category name.
my urls should look like this.
shop/Category/79/1/80/Clothing-Accessories
shop/Brand/79/1/80/my-brand
But the second routing rule in my list always shows up as
shop/Brand/159/1/80?brandName=Anchor-Crew
I thought with a different controller name it could tell which one to use but that does not seem to be the case. One possible solution is I give them both similar names such as 'slug'.
Update to include controllers
public async Task<IActionResult> Index([FromRoute] long id, int pageNumber, int pageSize, string brandName)
{
PaginatedList<Product> products = GetProducts(id, pageNumber, pageSize);
Brand brand = await _brandService.GetAsync(id);
public async Task<IActionResult> Index([FromRoute]long id, int pageNumber, int pageSize, string categoryName)
{
Category? category = await _categoryService.Get(id, true);
答案1
得分: 2
我认为以下引用来自文档在这里适用:
使用控制器和视图使用传统路由。默认路由:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
这个映射:
- 仅基于控制器和操作名称。
- 不基于命名空间、源文件位置或方法参数。
路由不考虑操作参数名称,所以从路由的角度来看,当仅使用段时,您定义了两条相同的路由。
传统路由按定义的顺序应用(请参见文档中的相应警告):
MapControllerRoute
和MapAreaRoute
根据它们被调用的顺序自动分配一个顺序值给它们的终点。这模拟了在没有路由系统提供与旧的路由实现相同的保证时,控制器的长时间行为。
因此,更改路由定义顺序会导致选择的控制器发生变化。
似乎将最后一个参数提供为查询字符串参数可以让路由选择正确的控制器(文档中找不到原因)。
您可以尝试使用“更具体”的路由来明确匹配早期声明的路由所需的控制器:
// 删除控制器模板参数并硬编码控制器
app.MapControllerRoute(
name: "CategoryPage",
pattern: "shop/category/{id}/{pageNumber}/{pageSize}/{*categoryName}",
defaults: new { area = "shop", controller = "category", action = "index" });
app.MapControllerRoute(
name: "BrandPage",
pattern: "shop/{controller}/{id}/{pageNumber}/{pageSize}/{*brandName}",
defaults: new { area = "shop", controller = "brand", action = "index" });
英文:
I think the following quotes from the docs are applicable here:
> Conventional routing is used with controllers and views. The default route:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
> This mapping:
> - Is based on the controller and action names only.
> - Isn't based on namespaces, source file locations, or method parameters.
Routing does not take in account action parameter names, so from the routing point of view you have defined two routes which are the same when only segments are used.
Conventional routes are applied in order of definition (see the corresponding warning in the docs):
> MapControllerRoute
and MapAreaRoute
automatically assign an order value to their endpoints based on the order they are invoked. This simulates long-time behavior of controllers without the routing system providing the same guarantees as older routing implementations.
so changing the route definition order has the observed effect of switching the selected controller.
It seems that providing last parameter as query string parameter lets the routing to select the correct controller (can't find in the docs why).
You can try using "more specific" route for the earlier declared route to match needed controller explicitly:
// remove controller template param and hardcode controller
app.MapControllerRoute(
name: "CategoryPage",
pattern: "shop/category/{id}/{pageNumber}/{pageSize}/{*categoryName}",
defaults: new { area = "shop", controller = "category", action = "index" });
app.MapControllerRoute(
name: "BrandPage",
pattern: "shop/{controller}/{id}/{pageNumber}/{pageSize}/{*brandName}",
defaults: new { area = "shop", controller = "brand", action = "index" });
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论