代码之家  ›  专栏  ›  技术社区  ›  nathanchere Jitendra Vyas

ASP.NET MVC路由冲突-输入变量的值为空

  •  6
  • nathanchere Jitendra Vyas  · 技术社区  · 16 年前

    我不知道为什么我的路线是冲突的。我的global.asax文件中有:

            routes.MapRoute(
            "CustomerView", "{controller}/{action}/{username}",
            new { controller = "Home", action = "Index", username = "" }
            );
    
            routes.MapRoute(
            "Default", "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = "0" }
            );
    

    到目前为止,一切都很好,除了我创建了这样的控制器操作:

        public ActionResult MyAction(int id)
        {
            //Do stuff here
            return View();
        }
    

    当我试着看的时候 http://mydomain/MyController/MyAction/5 我得到:

    “/”应用程序中的服务器错误。

    参数字典包含 的参数“id”的条目为空 的不可为空的类型“System.Int32” 方法'system.web.mvc.actionResult 轨道(Int32)'In “intouch.controllers.orderController”。 使参数的类型可选 应为引用类型或 可空类型。参数名称: 参数

    向我建议 id 未正确读取值。当然,以诺古,当我交换周围路线的顺序时,它工作得很好。到目前为止,我(公认的有限)的理解是,如果路由中指定的变量名与控制器操作定义中指定的变量名匹配,那么它将假定该变量名与顺序无关。显然我错了。交换顺序会导致其他控制器操作中断。在这种情况下,处理路由的正确方法是什么?

    2 回复  |  直到 16 年前
        1
  •  13
  •   Michael Paladino    16 年前

    您的示例的问题在于,匹配发生在第一个路由上,并且它将“5”作为用户名参数。您可以使用约束来限制每个参数接受的值,以实现您想要的。由于接受ID的“默认”路由比“customerview”路由更具限制性,因此我将首先列出“默认”路由,并对ID参数进行约束:

    routes.MapRoute(
        "Default", "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = "0" },
        new { id = @"\d+" } 
        );
    

    这将导致第一个路由仅在ID为整数值时匹配。然后,所有其他请求都将进入“customerview”路由,该路由将接收没有整数作为第三个参数的任何其他请求。

    退房 Creating a Route Constraint 关于约束的解释。

        2
  •  2
  •   Seth Petry-Johnson    16 年前

    我(公认有限)的理解 到目前为止,如果变量名 在路由中指定的与 在控制器操作中指定 定义,它假定 不管顺序如何。

    路由值到动作参数的绑定发生在框架确定要使用哪个路由之后。路由选择是使用“First Match Wins”启发式方法执行的:即使后来定义了“Better”路由,也会使用能够成功匹配传入请求的第一个路由。

    迈克尔的解决方案是正确的。您需要首先列出默认路由,使用路由约束仅匹配ID为数字的URL。你的第二条限制较少的路线应该是下一条。

    注释 :如果您遵循Michael的解决方案,如果您有任何用户名仅由数字组成的用户,则会遇到问题。您可以考虑在路由中添加一些其他识别因素,例如在第二个路由中添加关键字“user”:

    routes.MapRoute(
        "Default", "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = "0" },
        new { id = @"\d+" } 
     );
    
    routes.MapRoute(
        "CustomerView", "{controller}/{action}/user/{username}",
        new { controller = "Home", action = "Index", username = "" }
    );