我有一个名为SignUp的View Model,其EmailAddress属性设置如下:
[Required]
[DuplicateEmailAddressAttribute(ErrorMessage = "This email address already exists")]
public string EmailAddress { get; set; }
,自定义验证器如下所示:
public class DuplicateEmailAddressAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
PestControlContext _db = new PestControlContext();
int hash = value.ToString().GetHashCode();
if (value == null)
{
return true;
}
if (_db.Users.Where(x => x.EmailAddressHash == hash).Count() > 0)
return false;
else
return true;
}
}
我遇到的问题是,如果用户在注册表单上留下电子邮件地址字段为空,则应用程序抛出空引用异常错误(我认为它在数据库中查找“”并且无法找到它)。我不明白为什么这不是由必需属性处理 - 为什么它直接跳到自定义验证器?
答案 0 :(得分:0)
Required
属性会导致错误被添加到模型状态。但它不会使执行短路。该框架继续运行其他验证器,原因很简单,全部有关请求的错误需要一次性发送出去。理想情况下,您不希望服务开始时说错了,当用户在进行更正后重新提交请求时,服务会返回并说出其他一些错误等等。我想这将是一个烦恼。
答案 1 :(得分:0)
抛出NullReferenceException,因为在检查null之前调用了value.ToString()。由于您只在检查后需要哈希变量,您可以通过重新排序语句来解决这个问题:
if (value == null)
{
return true;
}
int hash = value.ToString().GetHashCode();
此外,您还可以在检查后将PestControlContext
移至null并使用using
语句正确处理它。
正如@Baldri所指出的那样,每个验证器都可以添加错误消息,并且所有验证器都会运行,即使前一个验证器已经发信号通知数据无效。此外,我不依赖于验证是按照您在使用属性标记属性时指定的顺序运行的(某些框架实现了自己的属性排序机制,以断言顺序是确定性的,例如优先级或先前属性)。
因此,我建议重新排序自定义验证器中的代码是最佳解决方案。