I have the following code in my RouteConfig.cs file:
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 }
);
}
Here is what I'm trying to achieve:
-----------------------------------------------------------------------
| 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 |
|---------------------------------------------------------------------|
The first 3 URLs are working, as expected. The problem is with the last 3. I know what's happening. The MVC route engine is evaluating the routes in the order they were mapped and when it sees http://localhost/Phoenix/47
, it is thinking 47
is a category and its going to Step2
before it gets to Step1
. I almost need the route engine to be smart enough to know that a number will be an orderId
.
How can I re-engineer my route list to get me the desired behavior?
Assuming that your methods in OrderController
are (in particular that orderId
is type of 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)
The you can add a route constraint to check if orderId
has been supplied and that it is an int
. Change the order of the routes to
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 }
);
and add a route constraint
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);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.