You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Url routing规则混淆:分类与品牌路由无法正确匹配的问题

ASP.NET Core 路由生成异常:品牌路由参数转为查询字符串问题

我为网站配置了两条相似的URL路由规则,分别对应分类(Category)与品牌(Brand):

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" });

两条规则仅controller参数和末尾的categoryName/brandName参数不同。预期生成的URL格式为:

shop/Category/79/1/80/Clothing-Accessories
shop/Brand/79/1/80/my-brand

但实际生成的品牌路由URL始终为:

shop/Brand/159/1/80?brandName=Anchor-Crew

原本以为不同的controller名称可让路由正确区分,但并未生效。我考虑将categoryName与brandName统一命名为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);
    // 省略其他代码
}

问题原因

ASP.NET Core的路由生成逻辑会优先匹配参数名称完全对应的路由模板。你的两条路由模板末尾参数名分别是categoryName和brandName,但系统仅靠controller值无法精准锁定对应路由,导致品牌路由的brandName参数匹配不到模板里的{*brandName},最终被当作查询字符串拼接。

解决方案:统一参数名为slug

这是最简洁的修复方案,具体步骤如下:

  1. 更新路由模板,把末尾的参数统一改成slug:
app.MapControllerRoute(
    name: "CategoryPage",
    pattern: "shop/{controller}/{id}/{pageNumber}/{pageSize}/{*slug}",
    defaults: new { area = "shop", controller = "category", action = "index" });

app.MapControllerRoute(
    name: "BrandPage",
    pattern: "shop/{controller}/{id}/{pageNumber}/{pageSize}/{*slug}",
    defaults: new { area = "shop", controller = "brand", action = "index" });
  1. 修改控制器参数,将brandName和categoryName替换为slug:
// 品牌控制器Index方法
public async Task<IActionResult> Index([FromRoute] long id, int pageNumber, int pageSize, string slug)
{
    PaginatedList<Product> products = GetProducts(id, pageNumber, pageSize);
    Brand brand = await _brandService.GetAsync(id);
    // 省略其他业务代码
}

// 分类控制器Index方法
public async Task<IActionResult> Index([FromRoute]long id, int pageNumber, int pageSize, string slug)
{
    Category? category = await _categoryService.Get(id, true);
    // 省略其他业务代码
}
  1. 生成URL时指定路由名称(推荐):
    为了避免路由匹配歧义,生成URL时显式指定路由名称,确保精准匹配:
// 生成分类页面URL
Url.RouteUrl("CategoryPage", new { controller = "category", id = 79, pageNumber = 1, pageSize = 80, slug = "Clothing-Accessories" })

// 生成品牌页面URL
Url.RouteUrl("BrandPage", new { controller = "brand", id = 159, pageNumber = 1, pageSize = 80, slug = "Anchor-Crew" })

替代方案:固化路由模板中的controller名称

如果不想修改参数名,也可以直接把controller名称写死在路由模板里,消除{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/brand/{id}/{pageNumber}/{pageSize}/{*brandName}",
    defaults: new { area = "shop", controller = "brand", action = "index" });

这种方式不需要修改控制器参数,也能让路由系统精准匹配到对应的模板。


内容的提问来源于stack exchange,提问作者James Andrew Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 15:01:11