2

我们有一个这样的路由配置:

  public static void RegisterRoutes(RouteCollection routes) {
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

     routes.MapRoute(
         name: "About",
         url: "{controller}/{action}/{aboutId}",
         defaults: new { controller = "Home", action = "About" }
     );

     routes.MapRoute(
         name: "Contact",
         url: "{controller}/{action}/{contactId}",
         defaults: new { controller = "Home", action = "Contact" }
     );

     routes.MapRoute(
         name: "Default",
         url: "{controller}/{action}/{id}",
         defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
     );
  }

您会注意到有两条路线具有一个强制性的额外参数。路线AboutContact.

在我们的应用程序中,我们有两个 url

www.myapp.com/Home/About/2效果很好。但是当我们浏览浏览器时,www.myapp.com/Home/Contact/5我们得到了可怕的路由异常:

The parameters dictionary contains a null entry for parameter 'contactId' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Contact(Int32)' in 'RoutingTest.Controllers.HomeController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.

如果我们改变路由的顺序,使它看起来像这样:

  public static void RegisterRoutes(RouteCollection routes) {
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

     routes.MapRoute(
         name: "Contact",
         url: "{controller}/{action}/{contactId}",
         defaults: new { controller = "Home", action = "Contact" }
     );

     routes.MapRoute(
         name: "About",
         url: "{controller}/{action}/{aboutId}",
         defaults: new { controller = "Home", action = "About" }
     );

     routes.MapRoute(
         name: "Default",
         url: "{controller}/{action}/{id}",
         defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
     );
  }

然后Contact网址有效,但About网址无效。

HomeController 看起来像这样:

  public class HomeController : Controller {
      public ActionResult Index() {
         ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

         return View();
      }

      public ActionResult About(int aboutId) {
         ViewBag.Message = "Your app description page.";

         return View();
      }

      public ActionResult Contact(int contactId) {
         ViewBag.Message = "Your contact page.";

         return View();
      }
   }

这似乎意味着无论控制器动作的名称如何,两个路由不能具有相同数量的参数。如果两个控制器动作有一个同名的参数,那么一切正常。我知道我可以开始做一些非常棘手的事情来解决这个问题,例如调用所有参数相同的名称或为操作提供无意义的参数来更改参数的数量,但我实际上想知道幕后发生了什么。

我该如何解决这个问题?

4

3 回答 3

5

您的问题的根源(不是双关语)不是路由不能具有相同数量的参数。他们能。问题是路由引擎将选择与传入请求匹配的第一个路由。您的路线仅在默认情况下有所不同,并且在模式匹配方面它们完全相同。因此,在每种情况下,您都应该走上正轨Contact

看起来您正在尝试根据操作设置不同的路线。我实际上看不出你为什么需要。

您可以使用以下内容来实现该效果。

public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Contact",
        url: "Home/Contact/{contactId}"
    );

    routes.MapRoute(
        name: "About",
        url: "Home/About/{aboutId}"
    );

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
 }

然而。我强烈建议不要使用这种方法,因为您的“默认”路由将是 Contact 路由。这意味着(在 Razor 下)@Html.ActionLink()和相关的方法将......错误。

老实说,如果您实际上只是使用...

public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
 }
于 2013-04-23T02:56:54.187 回答
2

在路由中明确指定控制器和/或操作以允许路由选择正确的路由:

 routes.MapRoute(
     name: "About",
     url: "{controller}/About/{aboutId}",
     defaults: new { controller = "Home", action = "About" }
 );

您还可以向参数添加约束以区分路由,但在您的情况下,这两个操作看起来都具有相同的整数参数。

于 2013-04-23T02:51:54.480 回答
2

难道你不能删除你的自定义路由并重用 {id} 参数(在你的操作代码中将 {contactId} 和 {aboutId} 变成“id”)吗?

public class HomeController : Controller {
  public ActionResult Index() {
     ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

     return View();
  }

  public ActionResult About(int id) {

     int aboutId = id;

     ViewBag.Message = "Your app description page.";

     return View();
  }

  public ActionResult Contact(int id) {

     int contactId = id;

     ViewBag.Message = "Your contact page.";

     return View();
  }

}

于 2013-04-24T04:57:02.227 回答