【问题标题】:Custom ValidationAttribute not displaying error自定义 ValidationAttribute 不显示错误
【发布时间】:2015-08-31 01:26:51
【问题描述】:

我编写了一个自定义 ValidationAttribute 来检查数据库中是否已经存在电子邮件。但是没有显示错误消息,并且在我提交表单后进行验证。 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]

【问题讨论】:

  • 不太清楚你想用var email = ... 线做什么? object value 包含属性的值。
  • 1 - 要在客户端验证,您必须创建一个自定义 JavaScript 函数。 2 - 您需要调用数据库才能验证表单,所以如果没有 ajax 调用就无法验证
  • @FabioLuz,您不需要自定义 javascript 函数。这都是 MVC 内置的(使用 [Remote] 属性,该属性在内部结合 jquery.validate.unobtrusive.js 进行 ajax 调用)
  • 是的,但是远程进行了 ajax 调用。我的意思是,在不调用服务器的情况下进行验证

标签: javascript c# asp.net-mvc


【解决方案1】:

IsValid 方法的object value 参数包含您的电子邮件属性的值,因此您不需要var emailvar emailValue 行代码。你的代码应该是

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

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

改为创建一个服务方法,该方法返回一个表明其有效的值(或在控制器中添加一个私有方法

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

还有一个ActionResult 用于客户端验证

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

然后将RemoteAttribute 应用到您的财产

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

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

【讨论】:

    猜你喜欢
    • 2011-12-30
    • 2012-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-12
    • 2016-09-19
    • 2021-07-08
    • 1970-01-01
    相关资源
    最近更新 更多