1

我正在尝试了解 MVC4 的路由

我想创建一个由 BrandName / ProductType / PageNumber 组成的 URL 结构

有时它可能只有品牌或产品类型,具体取决于您的过滤方式。

例如

Store/{BrandName}//{PaginationId} this is unique
Store/{ProductType}/{PaginationId} this is unique
Store/{BrandName}/{ProductType}/{PaginationId}
Store/{ProductType}/BrandName}/{PaginationId}

有什么帮助吗?

谢谢

4

2 回答 2

2

您必须注册以下路线:

// 1: Store/ProductType/BrandName/PaginationId
// (all parts must exists in the URL)
routes.MapRoute("ProductType", "Store/{productType}/{brandName}/{paginationId}",
   new { controller = "Store", action = "Index" },
   new { /* constraints */ });

// 2: Store/BrandName/ProductType/PaginationId 
// 3: Store/BrandName/ProductType 
// 4: Store/BrandName
// (both productType and paginationId can be missing)
routes.MapRoute("BrandProduct", "Store/{brandName}/{productType}/{paginationId}",
   new { controller = "Store", action = "Index", 
         productType = UrlParameter.Optional,
         paginationId = UrlParameter.Optional},
   new { /* constraints */ });

// 5: Store/ProductType/PaginationId
// (all parts must exists in the URL)
routes.MapRoute("ProductType", "Store/{productType}/{paginationId}",
  new { controller = "Store", action = "Index", 
         brandName = 0, paginationId = 0},
  new { /* constraints */ });

// Action Index should have 3 parameters: brandName, productType and paginationId
// brandName, productType and paginationId should be nullable 
// or reference type (class) to accept nulls

当接收到一个 URL 时,匹配它的第一个路由将处理它。所以必须有一种方法来区分路线。这可以使用约束来完成。约束是一个正则表达式,它决定接收到的值是否对参数有效。

假设在第一个映射中 ProductType 必须以“P”开头,您将添加此约束: new {productType="P.*"}

  • 如果用户键入这个 URL:/Store/P22/TheBrand/12,它将被第一个路由处理
  • 如果用户键入这个 URL:/Store/TheBrand/P22/12,由于约束,它不会被第一个路由处理,而是由第二个路由处理。

您必须区分路线 1 和 2,以及路线 3 和 5

如果没有正则表达式可以为您做到这一点,您可以使用一些额外的字符来修改路线,以便消除它们的歧义,即将 P- 和 B- 放在产品类型和品牌名称之前,如下所示:

// 1:
routes.MapRoute("ProductType", "Store/P-{productType}/B-{brandName}/{paginationId}",

// 2, 3, 4
routes.MapRoute("BrandProduct", "Store/B-{brandName}/P-{productType}/{paginationId}",

请记住,路由的处理顺序与它们注册的顺序相同。

编辑 - 对 OP 评论的回答:

如果您只想要类似于 ASP.NET 的行为,其中单个页面使用所有信息,请使用此映射:

routes.MapRoute("Store", "Store", new {controller="Store",action="Index"}}

使用此映射,所有额外信息将最终出现在查询字符串中,如下所示:

http://mysite/Store?ProductType=xxx&BrandName=yyy&PaginationId=23

如果您不提供某些参数,它们将被简单地从查询字符串中省略。

操作如下所示:

Index(string brandName, string prouctType, int? paginationId)

请注意,由于所有参数都是可选的,因此它们必须是可空的(引用类型如string或可空值类型如int?)。因此它们将自动从查询字符串中绑定,或者如果不存在则保留为空。

没有理由必须使用路由。您可以使用路由来获取“智能”网址,但您不需要这样做。

于 2013-07-10T10:08:26.413 回答
0

创建一个“主”浏览控制器,并制作BrandNameProductTypePaginationId作为参数。

结果:

Store/Browse?BrandName=XX&ProductType=YY&PaginationId=ZZ

然后,您可以重叠一些URL 重写逻辑(链接到其他 SO 答案)以实现所需的 URL 结构。

对于缺少参数的情况,我建议将它们设置为默认值:例如,如果您没有ProductType,您可以这样做:

Store/Browse?BrandName=XX&ProductType=ALL&PaginationId=ZZ

简而言之:如果它丢失了,默认它的值并使它成为你总是在任何地方都有值的地方。更容易处理,也更容易理解。

于 2013-07-10T08:59:00.593 回答