簡體   English   中英

查詢字符串參數的ASP.NET MVC約束

[英]ASP.NET MVC constraint for query string parameter

我有2個動作

public Action HasNumber(string name) { ... }

public Action DoesntHaveNumer(string name) { ... }

是否可以創建這樣的路由,使其根據name參數的值擊中一個或另一個?

例:

myApp/Home?name=qwe將命中DoesntHaveNumer

myApp/Home?name=q2e將命中HasNumber

name是必填參數

默認的Route類不與查詢字符串交互。 但是,您可以繼承它以添加其他功能。

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 }
        );
    }
}

並建立到頁面的鏈接,您需要將查詢字符串值添加到路由值集合。 您應該使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM