Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement Custom Model Validator in .NET Core

I need to implement custom Model Validator in .NET Core project. I need to do complex validation so I am avoiding Attribute validation. I used

public class UserModel : IValidatableObject {
    public int UserId { get; set; }
    public string UserName { get; set; }
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {

    }
}

But I need to separate Validation logic from Model So I found this in ASP.NET MVC -

public class ProjectModelValidatorProvider : ModelValidatorProvider {
    public override IEnumerable<ModelValidator> 
        GetValidators(ModelMetadata metadata, ControllerContext context) {
            if (metadata.ModelType == typeof(User))
                yield return new UserModelValidator(metadata, context);
    }
}

public class UserModelValidator : ModelValidator {
    public UserModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
    : base(metadata, controllerContext) { }

    public override IEnumerable<ModelValidationResult> Validate(object container) {
    var model = (User)Metadata.Model;
    if (string.IsNullOrEmpty(model.Login))
        yield return new ModelValidationResult { 
            MemberName = "Login", 
            Message = "Please specify Login" 
        };


    }
}

// register your Provider
ModelValidatorProviders.Providers.Add(new ProjectModelValidatorProvider());

With the help of ModelValidatorProvider and ModelValidator I achieved it. But how to achieve this in .NET Core such that with ModelState.IsValid I will be able to validate the model ?

like image 744
artista_14 Avatar asked Jan 27 '26 01:01

artista_14


1 Answers

In ASP.NET Core , you could customize a class that inherits IModelValidatorProvider interface like below :

public class CustomModelValidatorProvider : IModelValidatorProvider
{
    public void CreateValidators(ModelValidatorProviderContext context)
    {
        if (context.ModelMetadata.ContainerType == typeof(User))
        {
            context.Results.Add(new ValidatorItem
            {
                Validator = new UserModelValidator(),
                IsReusable = true
            });
        }
    }
}

public class UserModelValidator : IModelValidator
{
    private static readonly object _emptyValidationContextInstance = new object();
    public IEnumerable<ModelValidationResult> Validate(ModelValidationContext validationContext)
    {
        var validationResults = new List<ModelValidationResult>();


        if (validationContext.ModelMetadata.Name == "FirstName" && validationContext.Model == null)
        {
            var validationResult = new ModelValidationResult("", "FirstName is required");

            validationResults.Add(validationResult);

        }
        return validationResults;
    }
}

You could also add partial keyword in your model to separate Validation logic from Model , refer to following code:

public partial class User
{
    public int Id { get; set; }

    public string Gender { get; set; }

    [MaxLength(10)]
    public string FirstName { get; set; }

    [MaxLength(30)]
    public string LastName { get; set; }

    [EmailAddress]
    public string Email { get; set; }

    public List<UserGroups> UserGroups { get; set; }
    public List<Referal> Referals { get; set; }

}

public partial class User : IValidatableObject
{
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (string.IsNullOrEmpty(FirstName))
        {
            yield return new ValidationResult("FirstName is Required", new[] { "FirstName" });
        }
    }
}
like image 175
Xueli Chen Avatar answered Jan 29 '26 18:01

Xueli Chen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!