如何在ASP.NET MVC中定义此路由?

时间:2010-01-16 16:22:07

标签: c# asp.net-mvc routes

我有一个名为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完全不熟悉......

3 个答案:

答案 0 :(得分:9)

将参数year的名称更改为id,这将与MVC添加到项目中的默认路线相匹配。

因此,为了进一步说明,让我们看一下ASP.NET MVC添加的默认路由:

routes.MapRoute(
    "default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = "" }
);

在此路线中,您可以看到专门为controlleraction命名的三个令牌,传递给该操作的第三个令牌为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
);