Reputation: 2662
I'd like to implement some/any custom behavior for some data type, for example DateTime
or int
.
I've created a custom JsonConverter
which encompasses data received from the body of a request (unless it was specified as non-json), which allows me to do just that.
But if data is passed in the query string of a request, for example ?param1=helloWorld¶m2=123"
, they are handled differently and are not covered by my custom JsonConverter
.
I've read about creating/implementing my own Custom Model Binder, but those from the looks of it are for complex types, so I'm a bit lost on how exactly I can modify an incoming query string parameter, or if that's not possible - gain access to the whole query string, searching for the parameters I want to modify, and modifying those. (decoupled from Action
methods, similar to filters and whatnot.)
Thank you!
Upvotes: 4
Views: 4537
Reputation: 27793
creating/implementing my own Custom Model Binder, but those from the looks of it are for complex types, so I'm a bit lost on how exactly I can modify an incoming query string parameter
You can create and apply custom model binder to simple types parameter(s), like below.
public IActionResult Test(string param1, [ModelBinder(BinderType = typeof(Param2ModelBinder))]int param2)
{
decoupled from Action methods, similar to filters and whatnot.
If you do not want to directly apply custom model binder to action parameter, you can implement a custom model binder provider and specify the parameter your binder operates on, then add it to MVC's collection of providers.
Param2ModelBinder class
public class Param2ModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
// ...
// implement it based on your actual requirement
// code logic here
// ...
var model = 0;
if (bindingContext.ValueProvider.GetValue("param2").FirstOrDefault() != null)
{
model = JsonSerializer.Deserialize<int>(bindingContext.ValueProvider.GetValue("param2").FirstOrDefault());
// just for testing purpose
// if received data > 100
// set it to 100
if ((int)model > 100)
{
model = 100;
}
}
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
MyCustomBinderProvider class
public class MyCustomBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// specify the parameter your binder operates on
if (context.Metadata.ParameterName == "param2")
{
return new BinderTypeModelBinder(typeof(Param2ModelBinder));
}
return null;
}
}
Add custom model binder provider
services.AddControllersWithViews(opt=> {
opt.ModelBinderProviders.Insert(0, new MyCustomBinderProvider());
});
Test Result
Upvotes: 4