【问题标题】:How to implement Custom Model Validator in .NET Core如何在 .NET Core 中实现自定义模型验证器
【发布时间】:2019-09-03 19:32:34
【问题描述】:

我需要在 .NET Core 项目中实现自定义模型验证器。我需要进行复杂的验证,所以我避免了属性验证。我用过

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

    }
}

但我需要将验证逻辑与模型分开所以我在 ASP.NET MVC 中找到了this -

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());

ModelValidatorProviderModelValidator 的帮助下,我实现了它。但是如何在 .NET Core 中实现这一点,以便使用 ModelState.IsValid 我能够验证模型?

【问题讨论】:

    标签: c# .net asp.net-core .net-core


    【解决方案1】:

    在 ASP.NET Core 中,您可以自定义一个继承 IModelValidatorProvider 接口的类,如下所示:

    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;
        }
    }
    

    您也可以在模型中添加 partial 关键字以将 Validation 逻辑与 Model 分开,参考以下代码:

    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" });
            }
        }
    }
    

    【讨论】:

    • 我正在尝试实施第一个建议。有没有办法在 ModelValidator 中注入存储库?我在 services.AddMvc(options => { options.ModelValidatorProviders.Add(new ModelValidatorProvider()); }) 中注册了 modelvalidatorprovider
    • @artista_14 services.AddScoped(); services.AddMvc(options => { options.ModelValidatorProviders.Add(services.BuildServiceProvider().GetService() ); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    【解决方案2】:

    我尝试使用第一种方法。但是用户类 [MaxLength(10)] 属性没有更多工作。 我想要达到的效果是可以通过属性来控制,通过后就可以去自定义验证了。

    【讨论】:

    • 如果你将使用自定义验证器,属性将不起作用。您必须明确编写所有验证。
    • @artista_14 我试图读取 ValidationContext 类的一些字段。找到一个可以读取到属性的属性。我正在尝试手动触发模型验证。这似乎有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-03
    • 1970-01-01
    相关资源
    最近更新 更多