对于我的网站,我正在从xml(-nodes)动态构建链接。它发生在大多数情况下,产品详细信息的链接是这样构建的:
me.com/one/two/three/four/productdetail
在某些情况下,虽然第四个节点之后有第五个节点,但链接是:
me.com/one/two/three/four/five/productdetail
在我的行动方法中,如果它们都是字符串,我怎么能将这第五个'段'与productdetail区分开来?
public ActionResult Products(string one,string two,string 3,string four,string productdetail,string five = null) { }
我现在有这样定义的路线:
{controller} / {action} / {one} / {two} / {three} / {four} / {productdetail}
{控制器} / {行动} / {一个} / {2} / {3} / {4} / {5} / {产品详情}
(其中{one}到{five}是UrlParameter.Optional)
使用正则表达式的路由约束似乎没有帮助,因为它们都是字符串(并且它们都可以是非常相似的字符串)。
这甚至可能吗?
答案 0 :(得分:1)
解决此问题的最简单方法是为5,4,3和2参数注册路线。按顺序注册它们。
{controller}/{one}/{two}/{three}/{four}/{five}/{productdetail}
{controller}/{one}/{two}/{three}/{four}/{productdetail}
{controller}/{one}/{two}/{three}/{productdetail}
{controller}/{one}/{two}/{productdetail}
您无法为{controller} / {one} / {productdetail}注册路由,而无需创建路由约束以确保{one}不是{controller}的操作。
我强烈建议,如果你有哪些选项列表1 - 5可能会创建一个自定义路由约束来验证它们,这样你就不会意外地匹配你不想要的路线,但你应该是我安排了以上路线安全。
创建IRouteConstraint并不困难。下面是一些我以前用于路由约束的代码,它允许从特定控制器调用操作而无需指定控制器。一个例子是一个名为Home的控制器,其动作为“关于”,这个约束允许你调用/ about而不是/ home / about。
它与您想要做的事情相关,因为它会告诉您如何进行一些验证,以便在需要时区分{one}和{action}。
路线约束:
public class IsRootActionConstraint : IRouteConstraint
{
private List<string> _actions;
public IsRootActionConstraint(): this( "homecontroller")
{
}
public IsRootActionConstraint(string ControllerName)
{
Type _type = Assembly
.GetCallingAssembly()
.GetTypes()
.Where(type => type.IsSubclassOf(typeof(Controller)) && type.Name.ToLower() == ControllerName.ToLower())
.SingleOrDefault();
if (_type != null)
{
_actions = (from methods in _type.GetMethods() where typeof(ActionResult).IsAssignableFrom(methods.ReturnType) select methods.Name.ToLower()).ToList();
}
}
#region IRouteConstraint Members
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
return _actions.Contains((values["action"] as string).ToLower());
}
#endregion
}
当你在global.asax中注册你的路线时:
routes.MapRoute(
"Home",
"{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { IsRootAction = new CAA.Utility.Constraints.IsRootActionConstraint() } // Route Constraint
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
在您的情况下,验证{one}与{controller}中的路由不匹配应该不会太困难。您可以将反射代码移动到Match方法中,并使用控制器的路径值中的名称来查找操作。
答案 1 :(得分:0)
通过两条独立的路线,一条有五个元素,另一条有四个元素,这些路线可以到达同一个地方。一个通过{五}而另一个没通过。
编辑:如果两种模式相同,那么唯一的方法是使用约束来区分不同的值。
答案 2 :(得分:0)
我认为您可以对路线声明进行一些更改以满足您的期望。
现在
答案 3 :(得分:0)
如果在您的情况下,您无法设置路由约束,那么您最好的选择是更改您的路由,以便ASP.NET MVC可以确切知道哪个是您的产品详细信息参数,以避免任何混淆使用可选的{five}。
让您的产品详细信息前面有一些特定的字符串,这些字符串绝不会发生在一到五个值中,例如:
{controller}/{action}/{one}/{two}/{three}/{four}/p/{productdetail}
{controller}/{action}/{one}/{two}/{three}/{four}/{five}/p/{productdetail}
这将解决您的问题。