Change URL parameters with routing in MVC 4

Some of my API functions allow you to use parameters called the attribute and attribute attribute (singular), which means that the expected URL will be in the format

SomeController / SomeAction aaa = BBB &? Attribute = ccc &. AttributeDelimiter = ddd

I would also like to allow plural support in these parameter names - 'attributes' and 'attributesDelimiter'.

  • Is there any way to rewrite url in RouteConfig? (conversion of plural names to singular)
  • If this is not possible or it would not be best practice, what would be the best way to do such a rewrite?
0
source share
1 answer

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

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

Using

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 according to the properties of your models, regardless of whether the value is indicated as a single or plural, the values ​​will be filled. If both singular and plural numbers are included in the query string, priority is given particular importance.

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

Source: https://habr.com/ru/post/1668462/


All Articles