You could customize QueryStringValueProvider like below :
SeparatedQueryStringValueProvider
public class SeparatedQueryStringValueProvider : QueryStringValueProvider
{
private readonly string _key;
private readonly string _separator;
private readonly IQueryCollection _values;
public SeparatedQueryStringValueProvider(IQueryCollection values, string separator)
: this(null, values, separator)
{
}
public SeparatedQueryStringValueProvider(string key, IQueryCollection values, string separator)
: base(BindingSource.Query, values, CultureInfo.InvariantCulture)
{
_key = key;
_values = values;
_separator = separator;
}
public override ValueProviderResult GetValue(string key)
{
var result = base.GetValue(key);
if (_key != null && _key != key)
{
return result;
}
if (result != ValueProviderResult.None && result.Values.Any(x => x.IndexOf(_separator, StringComparison.OrdinalIgnoreCase) > 0))
{
var splitValues = new StringValues(result.Values
.SelectMany(x => x.Split(new[] { _separator }, StringSplitOptions.None)).ToArray());
return new ValueProviderResult(splitValues, result.Culture);
}
return result;
}
}
Add an IValueProviderFactory. Factories are – as the name suggests – responsible for providing instances of value providers. Our factory is very simple :
public class SeparatedQueryStringValueProviderFactory : IValueProviderFactory
{
private readonly string _separator;
private readonly string _key;
public SeparatedQueryStringValueProviderFactory(string separator) : this(null, separator)
{
}
public SeparatedQueryStringValueProviderFactory(string key, string separator)
{
_key = key;
_separator = separator;
}
public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
{
context.ValueProviders.Insert(0, new SeparatedQueryStringValueProvider(_key, context.ActionContext.HttpContext.Request.Query, _separator));
return Task.CompletedTask;
}
}
To apply the value provider globally to our entire API, we can register the factory in the MVC Options, at application startup.
services.AddMvc(opts =>
{
opts.ValueProviderFactories.Insert(0, new SeparatedQueryStringValueProviderFactory(","));
});
Note: the value provider is applied against a method (an action), not against an individual parameter of that action. This means that typically, if you create a custom value provider strategy it would be applied to all parameters of an action.
For how to remedy this defect, you can refer to this link : https://www.strathweb.com/2017/07/customizing-query-string-parameter-binding-in-asp-net-core-mvc/