我希望通过实现
IClientModelValidator
接口。具体来说,我正在创建一个
NotEqualTo
(后来
EqualTo
)将一个输入值与另一个输入值进行比较的验证属性。
为了提供一个好的UX,我想在错误消息中使用两个输入的显示名称:“例如,密码不能与电子邮件相同”。
这显然已经做了一百万次了,而且有很多例子,但是它们要么是用于MVC的早期版本,要么不使用其他属性的显示名称。
下面是到目前为止我所拥有的。我已经设法通过
Display
服务器端的属性
IsValid(...)
方法,但我无法解决如何为客户端执行类似操作
AddValidation(...)
方法。
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class NotEqualToAttribute : ValidationAttribute, IClientModelValidator
{
private const string defaultErrorMessage = "{0} cannot be the same as {1}.";
public string OtherProperty { get; private set; }
public NotEqualToAttribute(string otherProperty) : base(defaultErrorMessage)
{
this.OtherProperty = otherProperty;
}
public override string FormatErrorMessage(string name)
{
string.Format(base.ErrorMessageString, name, this.OtherProperty);
}
public void AddValidation(ClientModelValidationContext context)
{
context.Attributes.Add("data-val", "true");
context.Attributes.Add("data-val-notequalto", this.FormatErrorMessage(context.ModelMetadata.GetDisplayName());
context.Attributes.Add("data-val-notequalto-otherproperty", this.otherProperty);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == null)
return ValidationResult.Success;
PropertyInfo otherProperty = validationContext.ObjectInstance.GetType().GetProperty(this.OtherProperty);
object otherValue = otherProperty.GetValue(validationContext.ObjectInstance, null);
if (!value.Equals(otherValue))
return ValidationResult.Success;
DisplayAttribute display = otherProperty.GetCustomAttribute<DisplayAttribute>();
string otherName = display?.GetName() ?? this.OtherProperty;
return new ValidationResult(string.Format(defaultErrorMessage, validationContext.DisplayName, otherName));
}
}