MVC路由没有给出期望的路由

时间:2016-06-15 22:37:09

标签: c# asp.net-mvc routes

我的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

如何重新设计路线列表以获得理想的行为?

1 个答案:

答案 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);
    }
}
相关问题