自定义ValidationAttribute不显示错误

本文关键字:错误 显示 ValidationAttribute 自定义 | 更新日期: 2023-09-27 18:10:24

我写了一个自定义ValidationAttribute来检查Email是否已经存在于Db中。但是没有显示错误消息,并且在提交表单之后才进行验证。HTML包含对javascript文件的引用,以显示此消息,但仍然没有结果。然而,其他属性工作正常,并显示各自的消息。

public class NoDuplicateEmail : ValidationAttribute
{

     protected override ValidationResult IsValid(object value, ValidationContext validationContext)
     {
          var context = new MhotivoContext();
         var email = validationContext.ObjectInstance.GetType().GetProperties(
             ).FirstOrDefault(prop => IsDefined(prop, typeof(NoDuplicateEmail)));
         var emailValue = (string)email.GetValue(validationContext.ObjectInstance);
         if(context.Users.FirstOrDefault(x => x.Email == emailValue)!=null)
             return new ValidationResult("Email is in use!");
         return ValidationResult.Success;
     } 
}

<代码>

    [Required(ErrorMessage = "Email is required")]
    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email")]
    [NoDuplicateEmail]

自定义ValidationAttribute不显示错误

var email方法的IsValid参数包含您的电子邮件属性的值,因此您的var emailValue[Remote]行代码是不必要的。你的代码应该是

public class NoDuplicateEmail : ValidationAttribute
{
  private const string _DefaultErrorMessage = "Email {0} is in use!"
  public NoDuplicateEmail() : : base(_DefaultErrorMessage)
  {
  }
  protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  {
    var context = new MhotivoContext();
    if (value != null)
    {
      var email = (string)value;
      if(context.Users.FirstOrDefault(x => x.Email == emailValue) != null)
      {
        return new ValidationResult(FormatErrorMessage(email));
      }
    }
    return ValidationResult.Success;
  }
}

然而,你不应该在验证属性中访问数据库资源(这不是它的责任,你的代码不可能进行单元测试)。您应该使用ActionResult属性进行客户端验证,并调用服务进行服务器端验证。

创建一个服务方法,返回一个值来指示它的有效性(或者在你的控制器中添加一个私有方法

)
private bool isEmailInUse(string email)
{
  return context.Users.Any(x => x.Email == email)
}

RemoteAttribute用于客户端验证

public JsonResult IsUniqueEmail(string email) // the parameter name must match the property name
{
  bool isInUse = isEmailInUse(email);
  return Json(!isInUse, JsonRequestBehavior);
}

然后应用CC_8属性

[Remote("IsUniqueEmail", yourControllerName, ErrorMessage = "The email is already in use")]
public string Email { get; set; }

最后,在POST方法中(以防恶意用户,或者javascript已被禁用)

public ActionResult YourMethod (YourModel model)
{
  if (isEmailInUse(model.Email)
  {
    // add a ModelState error and return the view
  } 
}

或者在保存时捕获异常(假设数据库字段有唯一约束)