我有一个名为Movie
的控制器,其动作名为ByYear
,以年份为参数:
public ActionResult ByYear(int year)
{
ViewData["Title"] = string.Format("Movies released in {0}", year);
var repository = MvcApplication.GetRepository();
var movies = repository.Medias
.OfType<Movie>()
.Where(m => m.Year == year);
return View("Index", movies);
}
我想使用以下网址访问此操作: / Movie / ByYear / {year} ,但此操作的唯一有效路线是: / Movie / ByYear ?年= {年}
我尝试在我的应用程序的RegisterRoutes
方法中添加新路由,但我找不到获得所需结果的方法......
有谁能告诉我如何实现这个目标?
注意:这实际上与this question非常相似,但没有接受答案,而且最高的投票答案对我来说没有任何意义,因为我对MVC完全不熟悉......
答案 0 :(得分:9)
将参数year
的名称更改为id
,这将与MVC添加到项目中的默认路线相匹配。
因此,为了进一步说明,让我们看一下ASP.NET MVC添加的默认路由:
routes.MapRoute(
"default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
在此路线中,您可以看到专门为controller
,action
命名的三个令牌,传递给该操作的第三个令牌为id
。当请求进入您的应用程序时,ASP.NET MVC将分析当前映射的路由,并尝试通过对您的控制器使用反射来查找与它们匹配的方法签名。
当它查看您的Movie
控制器时,它会看到一个名为ByYear
的操作,但该方法采用名为year
的整数,而不是id
。这就是为特定操作创建/Movie/ByYear?year={year}
时最终会出现ActionLink
之类的内容的原因。所以要解决这个问题,你有两个选择:
解决此问题的第一个也是最简单的方法是只更改Action的方法签名,以接受名为id
的参数,这是我上面推荐的。这样可以正常工作,但是当我稍后回到那个源并且想知道你为什么调用那个参数id
时,我可以看到它可能会引起一些混乱。
第二种方法是添加与该方法签名匹配的另一个路由。要执行此操作,您应该打开Global.asax并添加以下内容(未经测试,但应该可以使用):
routes.MapRoute(
"MoviesByYear",
"Movies/ByYear/{year}",
new { controller = "Movie", action = "ByYear" }
);
此路由是硬编码的,是的,但它不会破坏系统中的其他路由,并且它允许您调用方法参数year
。
编辑2:另外需要注意的是,路由引擎会在找到的匹配您请求的第一条路线上停止,因此任何自定义路线都应添加之前默认路线,这样您就可以了确定他们会被找到。
答案 1 :(得分:4)
好的,我刚刚知道该怎么做。我只需要在>>默认路线之前创建新路线 ...我认为订单没有任何意义
routes.MapRoute(
"MovieByYear", // Route name
"Movie/ByYear/{year}", // URL with parameters
new { controller = "Movie", action = "ByYear" } // Parameter defaults
);
编辑:有没有更简单的方法? (不涉及重命名参数)。我希望能够做到这样的事情:
[Route("/Movie/ByYear/{year}")]
public ActionResult ByYear(int year)
{
...
答案 2 :(得分:2)
除了设计注意事项,如果你不想重命名参数,你可以添加类似下面的路线,它强制使用年份参数
routes.MapRoute(
"MovieByYear", // Route name
"Movie/ByYear/{year}", // URL with parameters
new { controller = "Movie", action = "ByYear" },
new { year = @"\d+" } // Parameter defaults
);