Changing URL parameters with routing in MVC 4

前端 未结 1 553
不思量自难忘°
不思量自难忘° 2021-01-26 00:24

Several of my API functions allow parameters called \'attribute\' and \'attributeDelimiter\' (in singular), meaning the expected URL would be in the format of

SomeContr

1条回答
  •  不思量自难忘°
    2021-01-26 00:51

    MVC does not use routing for query string values. Query string values are provided to action methods by value providers. So, to solve this issue you just need a custom value provider to handle the case of singular or plural.

    Example

    using System;
    using System.Collections.Specialized;
    using System.Globalization;
    using System.Web.Mvc;
    
    public class SingularOrPluralQueryStringValueProviderFactory : ValueProviderFactory
    {
        private readonly string singularKey;
        private readonly string pluralKey;
    
        public SingularOrPluralQueryStringValueProviderFactory(string singularKey, string pluralKey)
        {
            if (string.IsNullOrEmpty(singularKey))
                throw new ArgumentNullException("singularKey");
            if (string.IsNullOrEmpty(pluralKey))
                throw new ArgumentNullException("pluralKey");
    
            this.singularKey = singularKey;
            this.pluralKey = pluralKey;
        }
    
        public override IValueProvider GetValueProvider(ControllerContext controllerContext)
        {
            return new SingularOrPluralQueryStringValueProvider(this.singularKey, this.pluralKey, controllerContext.HttpContext.Request.QueryString);
        }
    }
    
    public class SingularOrPluralQueryStringValueProvider : IValueProvider
    {
        private readonly string singularKey;
        private readonly string pluralKey;
        private readonly NameValueCollection queryString;
    
    
        public SingularOrPluralQueryStringValueProvider(string singularKey, string pluralKey, NameValueCollection queryString)
        {
            if (string.IsNullOrEmpty(singularKey))
                throw new ArgumentNullException("singularKey");
            if (string.IsNullOrEmpty(pluralKey))
                throw new ArgumentNullException("pluralKey");
    
            this.singularKey = singularKey;
            this.pluralKey = pluralKey;
            this.queryString = queryString;
        }
    
        public bool ContainsPrefix(string prefix)
        {
            return this.GetSingularOrPluralValue(prefix) != null;
        }
    
        public ValueProviderResult GetValue(string key)
        {
            var value = this.GetSingularOrPluralValue(key);
            return (value != null) ? 
                new ValueProviderResult(value, value.ToString(), CultureInfo.InvariantCulture) : 
                null;
        }
    
        private bool IsKeyMatch(string key)
        {
            return (this.singularKey.Equals(key, StringComparison.OrdinalIgnoreCase) ||
                this.pluralKey.Equals(key, StringComparison.OrdinalIgnoreCase));
        }
    
        private string GetSingularOrPluralValue(string key)
        {
            if (this.IsKeyMatch(key))
            {
                return this.queryString[this.singularKey] ?? this.queryString[this.pluralKey];
            }
            return null;
        }
    }
    

    Usage

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
    
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
    
            // Insert our value provider factories at the beginning of the list 
            // so they override the default QueryStringValueProviderFactory
            ValueProviderFactories.Factories.Insert(
                0, new SingularOrPluralQueryStringValueProviderFactory("attribute", "attributes"));
            ValueProviderFactories.Factories.Insert(
                1, new SingularOrPluralQueryStringValueProviderFactory("attributeDelimiter", "attributesDelimiter"));
        }
    }
    

    Now in your action methods or even on properties of your models, whether the value is specified as singular or plural in the query string, the values will be populated. If both singular and plural are included in the query string, the singular value takes precedence.

    public ActionResult Index(string attribute, string attributeDelimiter)
    {
        return View();
    }
    

    0 讨论(0)
提交回复
热议问题