[HttpGet("test/{value}")]
public IActionResult Test(MyEnum value)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
}
Currently, if you send a request to test/999, ModelState.IsValid will be true regardless of whether Enum.IsDefined(typeof(MyEnum), 999) is true or not. However, if you send a request to test/abc and there is no abc member defined in MyEnum, ModelState.IsValid will be false. I think that's probably because strings are bound to enum parameters via Enum.Parse, while numerical values are directly set (and thus any value valid for the underlying enum type will be accepted).
Wouldn't it be more consistent if validation was made on both? If this would be a breaking change, then can we have a new constraint or attribute that does this validation? Or maybe a [easy, simple, obvious] way to tell ASP.NET to not try to deserialize the paramater to an int (so that the client would be forced to use the string representation of the enum)?
This isn't a bad idea at all.
For background, we don't implement any special type handling from enums, we just use the built-in type converter, but this isn't a bad idea at all.
If this would be a breaking change, then can we have a new constraint or attribute that does this validation?
If we added this by default we could also have a knob to turn it off globally or per-model
While this isn't implemented, is there a way to add some sort of custom validator to do that?
Yes, I was start by implementing IModelValidatorProvider. Your validator provider should create a custom validator each time it's called with an appropriate type.
https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IModelValidatorProvider.cs
https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IModelValidator.cs
Thanks!
The issue here with this is that the type converter for enum supports using integers, and will allow integral values that don't match the enum values. I'd suggest that rather than a validator this should be done in the model binder.
/cc @Eilon we should look at fixing this since users have a reasonable expectation that we validate this.
Ok, moving to 2.1. I agree that we should implement validation for this in a way that a developer would reasonably expect to work.
On discussing with @dougbu , came to know that there is an EnumDataTypeAttribute from DataAnnotations which can be used to validate an Enum type. I have tried it and it works. However I see that the scenario (or repro) in the original post shows using the Enum as a parameter directly, in which case this does not work as validation of data annotation attributes on parameters is not supported (right?).
@rynowak we needn't do anything here anymore?
We do plan to support data annotations on parameters and other "top level" bindings.
However, that doesn't change the fact that a user's expectations are left completely unsatisfied with the current behavior of enums. That's what we want to fix. It's good to know that there's a "workaround," but we decided that having to use a workaround isn't good enough.