我的MVC2应用程序使用一个组件,使后续的AJAX调用回到同一个动作,这会导致服务器上的各种不必要的数据访问和处理。组件供应商建议我将这些后续请求重新路由到不同的操作。后续请求的不同之处在于它们有一个特定的查询字符串,我想知道是否可以在路由表中对查询字符串设置约束。
例如,初始请求带有http://localhost/document/display/1之类的网址。这可以通过默认路由处理。我想通过检测网址中的“供应商”来编写自定义路由来处理http://localhost/document/display/1?vendorParam1=blah1&script=blah.js和http://localhost/document/display/1?vendorParam2=blah2&script=blah.js等网址。
我尝试了以下操作,但它会抛出System.ArgumentException: The route URL cannot start with a '/' or '~' character and it cannot contain a '?' character.
:
routes.MapRoute(
null,
"Document/Display/{id}?{args}",
new { controller = "OtherController", action = "OtherAction" },
new RouteValueDictionary { { "args", "vendor" } });
我可以编写一条考虑查询字符串的路由吗?如果没有,你还有其他想法吗?
更新:简单地说,我是否可以编写路由约束,以便将http://localhost/document/display/1路由到DocumentController.Display
操作,但http://localhost/document/display/1?vendorParam1=blah1&script=blah.js路由到{{1}动作?最后,我希望查询字符串中包含“vendor”的任何URL都路由到VendorController.Display
操作。
我知道第一个URL可以由默认路由处理,但第二个怎么办?是否可以这样做?经过大量的反复试验,看起来答案是“不”。
答案 0 :(得分:8)
QueryString参数可以在约束中使用,但默认情况下不支持。 Here您可以在ASP.NET MVC 2中找到一篇描述如何实现它的文章。
正如荷兰语,这是实施。添加'IRouteConstraint'类:
public class QueryStringConstraint : IRouteConstraint
{
private readonly Regex _regex;
public QueryStringConstraint(string regex)
{
_regex = new Regex(regex, RegexOptions.IgnoreCase);
}
public bool Match (HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
// check whether the paramname is in the QS collection
if(httpContext.Request.QueryString.AllKeys.Contains(parameterName))
{
// validate on the given regex
return _regex.Match(httpContext.Request.QueryString[parameterName]).Success;
}
// or return false
return false;
}
}
现在您可以在路线中使用它:
routes.MapRoute("object-contact",
"{aanbod}",
/* ... */,
new { pagina = new QueryStringConstraint("some|constraint") });
答案 1 :(得分:2)
您不需要这样的路线。它已由默认模型绑定器处理。查询字符串参数将自动绑定到操作参数:
public ActionResult Foo(string id, string script, string vendorname)
{
// the id parameter will be bound from the default route token
// script and vendorname parameters will be bound from the request string
...
}
更新:
如果您不知道将传递的查询字符串参数的名称,您可以遍历它们:
foreach (string key in Request.QueryString.Keys)
{
string value = Request.QueryString[key];
}
答案 2 :(得分:-1)
这篇文章很旧,但你不能在默认路线之前写一条路线
这只会在args
中捕获带有“vendor”的路径routes.MapRoute(
null,
"Document/Display/{id}?{args}",
new { controller = "VendorController", action = "OtherAction" },
new {args=@".*(vendor).*"}//believe this is correct regex to catch "vendor" anywhere in the args
);
这将抓住其余的
routes.MapRoute(
null,
"Document/Display/{id}?{args}",
new { controller = "DisplayController", action = "OtherAction" }
);
没试过这个,我是MVC的新手,但我相信这应该有用吗?根据我的理解,如果约束不匹配,则不使用路线。所以它会测试下一条路线。由于您的下一条路线不对args使用任何约束,因此它应与路线匹配。
我尝试了这个,它对我有用。