我的MVC2应用程序可以指定查询字符串参数的路由约束吗?

时间:2010-11-24 16:26:00

标签: asp.net-mvc-2 routing components

我的MVC2应用程序使用一个组件,使后续的AJAX调用回到同一个动作,这会导致服务器上的各种不必要的数据访问和处理。组件供应商建议我将这些后续请求重新路由到不同的操作。后续请求的不同之处在于它们有一个特定的查询字符串,我想知道是否可以在路由表中对查询字符串设置约束。

例如,初始请求带有http://localhost/document/display/1之类的网址。这可以通过默认路由处理。我想通过检测网址中的“供应商”来编写自定义路由来处理http://localhost/document/display/1?vendorParam1=blah1&script=blah.jshttp://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可以由默认路由处理,但第二个怎么办?是否可以这样做?经过大量的反复试验,看起来答案是“不”。

3 个答案:

答案 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使用任何约束,因此它应与路线匹配。

我尝试了这个,它对我有用。