[英]ASP.NET MVC constraint for query string parameter
I have 2 actions 我有2个动作
public Action HasNumber(string name) { ... }
public Action DoesntHaveNumer(string name) { ... }
Is it possible to create such route that it will hit one or anothere depending on the value of name
parameter? 是否可以创建这样的路由,使其根据
name
参数的值击中一个或另一个?
Example: 例:
myApp/Home?name=qwe
will hit DoesntHaveNumer
myApp/Home?name=qwe
将命中DoesntHaveNumer
myApp/Home?name=q2e
will hit HasNumber
myApp/Home?name=q2e
将命中HasNumber
name
is a mandatory parameter name
是必填参数
The default Route class does not interact with the query string. 默认的Route类不与查询字符串交互。 But, you can inherit it to add additional functionality.
但是,您可以继承它以添加其他功能。
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
public class NumericCheckingQueryStringValueRoute : Route
{
private readonly string queryStringKey;
private readonly RouteValueDictionary defaultsIfNumeric;
private readonly RouteValueDictionary defaultsIfNonNumeric;
public NumericCheckingQueryStringValueRoute(
string url,
string queryStringKey,
object defaultsIfNumeric,
object defaultsIfNonNumeric)
: base(url, new MvcRouteHandler())
{
this.queryStringKey = queryStringKey;
this.defaultsIfNumeric = new RouteValueDictionary(defaultsIfNumeric);
this.defaultsIfNonNumeric = new RouteValueDictionary(defaultsIfNonNumeric);
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var result = base.GetRouteData(httpContext);
// If it matches, the result will be non-null
if (result != null)
{
var newResult = new RouteData(this, new MvcRouteHandler());
// Copy the route values from the base class
foreach (var value in result.Values)
{
newResult.Values[value.Key] = value.Value;
}
// Copy the data tokens from the base class
foreach (var token in result.DataTokens)
{
newResult.DataTokens[token.Key] = token.Value;
}
var requestQueryString = httpContext.Request.QueryString;
var queryStringValue = requestQueryString[this.queryStringKey];
if (string.IsNullOrEmpty(queryStringValue))
{
return null;
}
RouteValueDictionary defaultsToUse;
if (ContainsDigits(queryStringValue))
{
defaultsToUse = this.defaultsIfNumeric;
}
else
{
defaultsToUse = this.defaultsIfNonNumeric;
}
// Copy the numeric defaults to route values
foreach (var value in defaultsToUse)
{
newResult.Values[value.Key] = value.Value;
}
// We matched, return the result
return newResult;
}
// Return null if no match
return null;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
// We just pass this through. If you add the value as a route value
// when building ActionLink or RouteLink, it will automatically make
// it into a query string value because it is not part of the url argument.
return base.GetVirtualPath(requestContext, values);
}
// Fastest way to check for digits
// http://stackoverflow.com/questions/7461080/fastest-way-to-check-if-string-contains-only-digits
private bool ContainsDigits(string str)
{
foreach (char c in str)
{
if (c >= '0' && c <= '9')
return true;
}
return false;
}
}
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(
name: "CheckNumericName",
item: new NumericCheckingQueryStringValueRoute(
url: "Home",
queryStringKey: "name",
defaultsIfNumeric: new { controller = "Home", action = "HasNumber" },
defaultsIfNonNumeric: new { controller = "Home", action = "DoesntHaveNumer" }
)
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
And to build links to the page, you will need to add the query string value to the route values collection. 并建立到页面的链接,您需要将查询字符串值添加到路由值集合。 You should use RouteLink since you have it going to 2 different action methods.
您应该使用RouteLink,因为您将使用2种不同的操作方法。
@Html.RouteLink("Link with number", "CheckNumericName", new { name = "q2e" })
@Html.RouteLink("Link with no number", "CheckNumericName", new { name = "qwe" })
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.