I try to use IModelValidatorProvider
and IModelValidator
interfaces in my ASP.NET Core project for respective model validation.
Unfortunately it does not work as expected.
Namely my ModelValidator
class (implements IModelValidator
) returns only one error. As a result I see that ModelState
contains one error with the expected text. It is fine.
ModelState.ErrorsCount = 1
.
But the problem is new element is presented in ModelState.Values
.
It has a key Code.Code
instead of Code
where Code
is name of one of the model property. That is why the required text is not shown in validation field for Code
property on page view.
The situation is different if I use ModelState.AddModelError
method in the controller.
ModelState.AddModelError("Code", "something went wrong...");
ModelState.Values
does not contain additional element with key Code.Code
. It contains element with key Code
(ValidationState=Invalid
) and a error message is shown correctly.
I guess I am doing something wrong with model validators. But I am stuck and can't find the exact issue. Would be thankful for any advice.
Please find below the source code of my validators
public class CustomModelValidatorProvider : IModelValidatorProvider
{
public CustomModelValidatorProvider()
{
}
public void CreateValidators(ModelValidatorProviderContext context)
{
if (context.Results.Any(v => v.Validator.GetType() == typeof(MyCustomModelValidator)) == true)
{
return;
}
if (context.ModelMetadata.ContainerType == typeof(DealRegistrationViewModel))
{
context.Results.Add(new ValidatorItem
{
Validator = new MyCustomModelValidator(),
IsReusable = true
});
}
}
}
public class MyCustomModelValidator : IModelValidator
{
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context)
{
var model = context.Container as DealRegistrationViewModel;
if (context.ModelMetadata.ModelType == typeof(string)
&& context.ModelMetadata.Name == nameof(model.Code))
{
if (string.IsNullOrEmpty(model.Code) == true)
{
return new List<ModelValidationResult>
{
new ModelValidationResult(context.ModelMetadata.PropertyName, "Empty Code value is not accepted")
};
}
}
return Enumerable.Empty<ModelValidationResult>();
}
}
The validator is activated in startup.cs
like this
services.AddMvc(options =>
{
options.ModelValidatorProviders.Add(new CustomModelValidatorProvider());
});
Please find below with screenshot with ModelState.Values
content in case of ModelState.AddModelError
usage (works fine)
Please find below with screenshot with ModelState.Values
content in case of Model validators usage (it does not work fine)
You just need to change your code in your MyCustomModelValidator
like below:
if (string.IsNullOrEmpty(model.Code) == true)
{
return new List<ModelValidationResult>
{
new ModelValidationResult("", "Empty Code value is not accepted")
};
}