我的RouteConfig.cs文件中有以下代码:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Location",
url: "Order/Location",
defaults: new { controller = "Order", action = "Location" }
);
routes.MapRoute(
name: "Step3",
url: "Order/{location}/{category}/{item}/{id}/{orderId}",
defaults: new { controller = "Order", action = "Step3", orderId = UrlParameter.Optional }
);
routes.MapRoute(
name: "Step2",
url: "Order/{location}/{category}/{orderId}",
defaults: new { controller = "Order", action = "Step2", orderId = UrlParameter.Optional }
);
routes.MapRoute(
name: "Step1",
url: "Order/{location}/{orderId}",
defaults: new { controller = "Order", action = "Step1", orderId = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
这是我想要实现的目标:
-----------------------------------------------------------------------
| Url | Desired Action |
|--------------------------------------------------|------------------|
| http://localhost/Order/Phoenix | Step1 |
| http://localhost/Order/Phoenix/Parts | Step2 |
| http://localhost/Order/Phoenix/Parts/Plugs/12 | Step3 |
| http://localhost/Order/Phoenix/47 | Step1 |
| http://localhost/Order/Phoenix/Parts/47 | Step2 |
| http://localhost/Order/Phoenix/Parts/Plugs/12/47 | Step3 |
|---------------------------------------------------------------------|
正如预期的那样,前3个网址正在运行。问题在于最后的3.我知道发生了什么。 MVC路由引擎按照它们映射的顺序评估路由,当它看到http://localhost/Phoenix/47
时,它认为47
是一个类别,它到达Step2
之前到达Step1
1}}。我几乎需要路由引擎足够聪明才能知道一个数字是orderId
。
如何重新设计路线列表以获得理想的行为?
答案 0 :(得分:0)
假设您OrderController
中的方法(特别是orderId
的类型为int
)
// Order/{location}/{orderId}
public ActionResult Step1(string location, int? orderId)
// Order/{location}/{category}/{orderId}
public ActionResult Step2(string location, string category, int? orderId)
// Order/{location}/{category}/{item}/{id}/{orderId}
public ActionResult Step3(string location, string category, string item, int id, int? orderId)
您可以添加路线约束来检查是否已提供orderId
且它是int
。将路线的顺序更改为
routes.MapRoute(
name: "Step1",
url: "Order/{location}/{orderId}",
defaults: new { controller = "Order", action = "Step1", orderId = UrlParameter.Optional },
constraints: new { orderId = new OrderConstraint() }
);
routes.MapRoute(
name: "Step2",
url: "Order/{location}/{category}/{orderId}",
defaults: new { controller = "Order", action = "Step2", orderId = UrlParameter.Optional },
constraints: new { orderId = new OrderConstraint() }
);
routes.MapRoute(
name: "Step3",
url: "Order/{location}/{category}/{item}/{id}/{orderId}",
defaults: new { controller = "Order", action = "Step3", orderId = UrlParameter.Optional },
constraints: new { orderId = new OrderConstraint() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
并添加路线约束
public class OrderConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
string v = values["orderId"].ToString();
if (String.IsNullOrEmpty(v))
{
return true;
}
int value;
return int.TryParse(values["orderId"].ToString(), out value);
}
}