Created
July 10, 2018 07:33
-
-
Save geirsagberg/f06c376a23ff95f8176379e32e0b2e40 to your computer and use it in GitHub Desktop.
Delimited query string value provider
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Globalization; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Localization; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.AspNetCore.Mvc.ModelBinding; | |
using Microsoft.Extensions.Primitives; | |
namespace Utils | |
{ | |
/// <inheritdoc /> | |
/// <summary> | |
/// A <see cref="T:Microsoft.AspNetCore.Mvc.ModelBinding.IValueProviderFactory" /> that creates | |
/// <see cref="T:Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider" /> instances that | |
/// read optionally delimited values from the request query-string. | |
/// </summary> | |
public class DelimitedQueryStringValueProviderFactory : IValueProviderFactory | |
{ | |
private static readonly char[] DefaultDelimiters = {','}; | |
private readonly char[] delimiters; | |
public DelimitedQueryStringValueProviderFactory() | |
: this(DefaultDelimiters) | |
{ | |
} | |
public DelimitedQueryStringValueProviderFactory(params char[] delimiters) | |
{ | |
if (delimiters == null || delimiters.Length == 0) { | |
this.delimiters = DefaultDelimiters; | |
} else { | |
this.delimiters = delimiters; | |
} | |
} | |
/// <inheritdoc /> | |
public Task CreateValueProviderAsync(ValueProviderFactoryContext context) | |
{ | |
if (context == null) { | |
throw new ArgumentNullException(nameof(context)); | |
} | |
var valueProvider = new DelimitedQueryStringValueProvider( | |
context.ActionContext.HttpContext.Request.Query, | |
context.ActionContext.HttpContext.Features.Get<IRequestCultureFeature>().RequestCulture.Culture, | |
delimiters); | |
context.ValueProviders.Add(valueProvider); | |
return Task.CompletedTask; | |
} | |
} | |
public class DelimitedQueryStringValueProvider : QueryStringValueProvider | |
{ | |
private readonly IQueryCollection queryCollection; | |
public char[] Delimiters { get; } | |
public DelimitedQueryStringValueProvider( | |
IQueryCollection values, | |
CultureInfo culture, | |
char[] delimiters) | |
: base(BindingSource.Query, values, culture) | |
{ | |
queryCollection = values; | |
Delimiters = delimiters; | |
} | |
public override ValueProviderResult GetValue(string key) | |
{ | |
if (key == null) { | |
throw new ArgumentNullException(nameof(key)); | |
} | |
var values = queryCollection[key]; | |
if (values.Count == 0) { | |
return ValueProviderResult.None; | |
} | |
if (values.Any(x => Delimiters.Any(x.Contains))) { | |
var stringValues = new StringValues(values | |
.SelectMany(x => x.Split(Delimiters, StringSplitOptions.RemoveEmptyEntries)) | |
.ToArray()); | |
return new ValueProviderResult(stringValues, Culture); | |
} | |
return new ValueProviderResult(values, Culture); | |
} | |
} | |
public static class ValueProviderFactoriesExtensions | |
{ | |
/// <summary> | |
/// Allows parsing query strings on the form of ?array=value1,value2,value3 etc. | |
/// </summary> | |
public static void AddDelimitedValueProviderFactory( | |
this IList<IValueProviderFactory> valueProviderFactories, | |
params char[] delimiters) | |
{ | |
AddDelimitedQueryStringValueProviderFactory(valueProviderFactories, delimiters); | |
AddDelimitedFormValueProviderFactory(valueProviderFactories, delimiters); | |
} | |
private static void AddDelimitedFormValueProviderFactory(IList<IValueProviderFactory> valueProviderFactories, char[] delimiters) | |
{ | |
var formValueProviderFactory = valueProviderFactories.OfType<FormValueProviderFactory>().FirstOrDefault(); | |
if (formValueProviderFactory == null) { | |
valueProviderFactories.Insert(0, | |
new DelimitedFormValueProviderFactory(delimiters)); | |
} else { | |
valueProviderFactories.Insert(valueProviderFactories.IndexOf(formValueProviderFactory), | |
new DelimitedFormValueProviderFactory(delimiters)); | |
valueProviderFactories.Remove(formValueProviderFactory); | |
} | |
} | |
private static void AddDelimitedQueryStringValueProviderFactory(IList<IValueProviderFactory> valueProviderFactories, char[] delimiters) | |
{ | |
var queryStringValueProviderFactory = valueProviderFactories.OfType<QueryStringValueProviderFactory>().FirstOrDefault(); | |
if (queryStringValueProviderFactory == null) { | |
valueProviderFactories.Insert(0, | |
new DelimitedQueryStringValueProviderFactory(delimiters)); | |
} else { | |
valueProviderFactories.Insert(valueProviderFactories.IndexOf(queryStringValueProviderFactory), | |
new DelimitedQueryStringValueProviderFactory(delimiters)); | |
valueProviderFactories.Remove(queryStringValueProviderFactory); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment