public enum GroupBy
{
status = 0,
dueDate = 1,
requester = 2,
assignee = 3
}
I am using this enum in params of web api like this:-
public async Task<IActionResult> Dashboard(GroupBy groupBy)
My problem is when i am passing correct enum it will give output. But if I pass any invalid enum it will throw error which is built-in error of ASP.NET Core. I tried to implement but while calling this api it won't go inside my custom validator. When I am passing valid enum it will go inside my validator.
So, I want to implement custom validation for it. Somebody please help
When the value is incorrect, the model binder can't create the GroupBy instance and can't call custom validation on this instance.
A solution is to change the input parameter type to string and do manually the check and parse step :
public async Task<IActionResult> Dashboard(string groupBy)
{
if(!Enum.TryParse(groupBy, out GroupBy by))
{
ModelState.AddModelError(nameof(groupBy), $"The value is invalid. Valid value : {Enum.GetValues(typeof(GroupBy))}");
return BadRequest(ModelState);
}
return Ok(by);
}
Other solution is to override the model binder behavior. For this, you need create a custom binder :
public class GroupByBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
// Try to fetch the value of the argument by name
var modelName = "groupBy";
var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
if (valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
bindingContext.ModelState.SetModelValue(modelName, valueProviderResult);
var value = valueProviderResult.FirstValue;
// Check if the argument value is null or empty
if (string.IsNullOrEmpty(value))
{
return Task.CompletedTask;
}
// Custom validation
if (!Enum.TryParse(value, out GroupBy groupBy))
{
bindingContext.ModelState.AddModelError(modelName, $"The value is invalid. Valid value : {Enum.GetValues(typeof(GroupBy))}");
return Task.CompletedTask;
}
bindingContext.Result = ModelBindingResult.Success(groupBy);
return Task.CompletedTask;
}
}
And now you can :
public async Task<IActionResult> Dashboard2([ModelBinder(typeof(GroupByBinder))] GroupBy groupBy)
{
if(!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok(groupBy);
}
You can override this behavior to all GroupBy input parameter :
public class GroupByBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.ModelType == typeof(GroupBy))
{
return new BinderTypeModelBinder(typeof(GroupByBinder));
}
return null;
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.ModelBinderProviders.Insert(0, new GroupByBinderProvider());
});
}
}
Warning : Model Builder isn't used when the data come from JSON or XML content. More detail on the official documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With