具有客户端验证的自定义数据注释验证属性

Posted

技术标签:

【中文标题】具有客户端验证的自定义数据注释验证属性【英文标题】:Custom data annotation validation attribute with client side validation 【发布时间】:2017-12-13 07:25:34 【问题描述】:

我制作了一个自定义数据注释属性,用于验证我的数据库中是否已经存在这样的电子邮件:

   public class ValidateEmail : ValidationAttribute
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        
            using (var ctx = new myCtx())
            
                if (value != null)
                
                    var valueAsString = value.ToString().ToLower();
                    IEnumerable<string> email = ctx.Users.Where(x => x.Email != null).Select(x => x.Email);
                    if (email.Contains(valueAsString))
                    
                        var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                        return new ValidationResult(errorMessage);
                    
                
                return ValidationResult.Success;
            
        
    

在我的视图模型中我是这样设置的:

   [ValidateEmail(ErrorMessage = "Email exists")]
        [Required(ErrorMessage = "Required")]
        [RegularExpression(@"^([\w\.\-]+)@([\w\-]+)((\.(\w)2,3)+)$", ErrorMessage = "Invalid Email")]
        public string Email  get; set; 

这在页面重新加载时完美运行...但我现在想更改它,以便我启用客户端验证和消息显示而无需重新加载页面本身...

如何修改此验证属性以使其符合 jquery 在 .NET MVC 中的不显眼验证?

基于@Sayan 的链接,我实现了这样的功能:

   public class ValidateEmail : ValidationAttribute, IClientValidatable
    
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        
            var rule = new ModelClientValidationRule();
            rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
            rule.ValidationType = "emailvalidate";

            yield return rule;

        

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        
            using (var ctx = new myContext())
            
                if (value != null)
                
                    var valueAsString = value.ToString().ToLower();
                    IEnumerable<string> email = ctx.Users.Where(x => x.Email != null).Select(x => x.Email);
                    if (email.Contains(valueAsString))
                    
                        var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                        return new ValidationResult(errorMessage);
                    
                
                return ValidationResult.Success;
            
        
    

和客户端:

$.validator.addMethod("emailvalidate", function (value, element) 

    console.log("value: " + value + " " + element);
);
$.validator.unobtrusive.adapters.add("emailvalidate", function (options) 

      //adding rules for validator
    options.rules["emailvalidate"] = true;
    if (options.message) 
        options.messages["emailvalidate"] = options.message;
    

);

但是我现在在电子邮件字段中插入的任何电子邮件都像:

myemail@ymail.xyz 

我收到电子邮件存在的错误?

【问题讨论】:

有人吗? =) 如果要调用服务器方法,请使用 [Remote] 属性。不要将数据库调用放在ValidationAttribute 【参考方案1】:

您可以在ValidateEmail 验证属性中实现IClientValidatable,以向客户端提供data-val-xxx 属性。

然后,您可以编写 jQuery 不显眼的验证器和适配器,以使用 html 中呈现的 data-val-xxx 在客户端验证字段值。

请确保根据字段值是否有效分别从 jQuery 验证器返回 true(真值)或 false(假值)。

最后,将此自定义 jQuery 验证器脚本添加到您的视图中。

您可以找到更多详细信息here。虽然这篇博文呈现了一个稍微复杂的场景,但是看看如何使用IClientValidatable 以及如何编写 jQuery 不显眼的验证器就足够了。

希望这会有所帮助。

【讨论】:

嘿Sayan 非常感谢您的回复。我已经“部分”实现了它,但它总是显示电子邮件存在的错误消息...我将使用我写的解决方案编辑我的初始问题,你能看看吗? 我觉得我只是错过了一些零碎的拼图来完成这个..但我只是没有看到它xD @User987 请检查我更新的答案。确保根据字段值是否有效分别从 jQuery 验证器返回 true(真值)或 false(假值)。 嘿嘿,但是 IsValid 字段返回的是验证结果,不是布尔类型? 好的,现在接受你的回答,谢谢! :)

以上是关于具有客户端验证的自定义数据注释验证属性的主要内容,如果未能解决你的问题,请参考以下文章

使用数据注释和代码的自定义验证属性

具有 basicHttpBinding、传输安全性和基本客户端凭据类型的自定义 WCF 凭据验证器

jQuery Unobtrusive 客户端验证自定义属性

WCF 服务中的自定义证书验证

使用 IdentityServer 与创建基于 JWT 的自定义身份验证

在 Asp.net Core MVC 中定义自定义客户端验证规则