如何修复我的MVC3路由问题

4

我在我的ASP.NET MVC3应用程序中遇到了一些路由问题,确切地说是没有按照我的意愿工作。

Global.asax中的路由定义

routes.MapRoute(
            "News", // Route name
            "{lang}/{controller}/{action}/{page}/{id}", // URL with parameters
            new { lang = "pl", controller = "News", action = "Index", page = 1, id = UrlParameter.Optional } // Parameter defaults
        );

所以我希望在以下两种情况下使用它:

  1. /{lang}/{controller}/{action}/{page} - 跳转到特定分页的页面
  2. /{lang}/{controller}/{action}/{page}/{id} - 记录当前页面,并跳转到指定 id 的页面。

为了生成链接,我使用以下代码:

@Html.RouteLink(i.ToString(), "News", new { lang = ViewBag.Lang, page = i })

i表示页码,lang为语言参数。

控制器中,我使用Action来处理它:

public ViewResult Index(string lang, int page = 1)

问题

@Html.RouteLink 给了我一个链接 /pl/News/Index/2(当点击“2”时),但我的控制器没有处理它,页面仍然是“1”。所以当我点击两次相同的链接时,它会给出:/pl/News/Index/2/2,然后页面等于“2”。

如果有人能够解释一下它是如何工作的,并告诉我该怎么办才能解决这个问题?

非常感谢您的帮助。


这是一些非常棒的路由,但是我在你的控制器中没有看到 id(可选),难道不应该是 Index(string lang, int? id, int page = 1) 吗? :) - Patryk Ćwiek
你没有仔细阅读 :) 在索引操作中,我不使用id参数,我只需要它在其他操作中。 - Mateusz Rogulski
1
如果我理解正确的话,当你点击 /pl/News/Index/2 时,它会触发正确的 Index 动作,但是该动作中 page 的值却为1而不是2。难道没有其他路由与此链接匹配吗? - Juraj Suchár
我认为如果我使用@Html.RouteLink并给出路由名称,它应该采用特定的路由。但是如果URL不符合规则...它会采用默认值。嗯,我认为这就是问题所在,但我不知道为什么会发生这种情况以及如何更改它。 - Mateusz Rogulski
2个回答

2

我想你在这里缺失的是路由系统使用当前请求的变量值来生成出站规则。

例如,如果您在页面 /pl/News/Index/2 上,您有:

lang = "pl", controller = "News", action = "Index", page = 2

如果您尝试生成这样的规则
@Html.RouteLink(i.ToString(), "News")

路由系统将使用已经存在的变量,如langpage,并生成完全相同的URL - /pl/News/Index/2。

当然,在Html.RouteLink中传递的匿名类型中的值具有优先级,并将覆盖当前请求中的值。因此,在您的示例中,您应该考虑在生成链接时您所处的URL是什么

优先顺序如下:

  1. 在匿名类型中传递的变量
  2. 请求变量
  3. 路由中定义的默认值。

看起来这部分内容

lang = ViewBag.Lang

如果您不提供lang,则无用-因为它将从请求中获取-因此它将被保留。

更新(可能与本题无关):

您还应该记住,如果有多个规则匹配-路由系统将选择满足约束条件的第一个规则(例如来自请求的值不应与默认变量冲突)

更新2

路由系统使用请求变量直到第一个明确指定的变量(通过匿名类型),因此如果您明确指定lang,则不会重用请求变量(在您的情况下,因为lang 是URL中的第一个段)


谢谢您的回答,但我不确定是否理解您的意思。您建议我更改什么吗?当我使用@Html.RouteLink并给出特定的路由名称时,它会采用正确的规则,是吗?但我发现它没有覆盖“page”值。那我该怎么做才能实现这一点呢? - Mateusz Rogulski
@MateuszRogulski - 是的,当您使用RouteLink时,它会使用指定的规则(这就是为什么我提到我的更新与您的情况无关)。您能否发布整个代码(所有规则,所有操作和完整视图)- 我刚刚尝试了您的规则,并且在新的MVC项目中它可以正常工作(页面值被覆盖)。 - Ventsyslav Raikov
它采用了错误的路由规则。但在这种情况下,我不知道@Html.RouteLink如何工作,因为它获取“默认”路由。但是我通过更改我的路由规则来解决了这个问题。感谢您的帮助。 - Mateusz Rogulski

0

我认为你的问题部分在于你有点违反了惯例,而且由于MVC依赖惯例来成功路由,所以你的映射有些出毛病。

我建议你像这样重新编写你的路由:

routes.MapRoute(
            "News", // Route name
            "{controller}/{action}/{lang}/{id}/{page}", // URL with parameters
            new { controller = "News", action = "Index", lang = "pl", page = 1, id = UrlParameter.Optional } // Parameter defaults
        );

看起来,URL最常见的情况可能是这样的:

http://yourdomainhere/news/pl/some-sort-of-permalink/1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接