您可以访问 ASP.NET Core 2.1 MVC 客户端验证的其他属性的元数据吗?
Can you access the metadata of other properties for ASP.NET Core 2.1 MVC client side validation?
我正在考虑通过实现 IClientModelValidator
接口来实现一些非常简单的客户端验证。具体来说,我正在创建一个 NotEqualTo
(后来是 EqualTo
)验证属性,它将一个输入的值与另一个进行比较。
为了提供良好的用户体验,我想在错误消息中使用两个输入的显示名称:例如 "Password cannot be the same as Email"。
这显然已经完成了一百万次并且周围有很多示例,但它们要么是针对以前版本的 MVC,要么没有使用其他版本的显示名称属性。
以下是我目前所拥有的。我已经设法通过服务器端 IsValid(...)
方法中的 Display
属性获取显示名称,但我不知道如何为客户端 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));
}
}
通常我在休息后自己解决了这个问题,只是把它留在这里以防它帮助其他人(或者有更好的解决方案):
public void AddValidation(ClientModelValidationContext context)
{
context.Attributes.Add("data-val", "true");
string otherName =
context.ModelMetadata.ContainerMetadata.Properties
.Single(p => p.PropertyName == this.OtherProperty)
.GetDisplayName();
context.Attributes.Add("data-val-notequalto",
string.Format(defaultErrorMessage, context.ModelMetadata.GetDisplayName(), otherName)
);
}
您可以通过 ClientModelValidationContext.ModelMetadata.ContainerMetadata.Properties
获取其他属性的元数据
我正在考虑通过实现 IClientModelValidator
接口来实现一些非常简单的客户端验证。具体来说,我正在创建一个 NotEqualTo
(后来是 EqualTo
)验证属性,它将一个输入的值与另一个进行比较。
为了提供良好的用户体验,我想在错误消息中使用两个输入的显示名称:例如 "Password cannot be the same as Email"。
这显然已经完成了一百万次并且周围有很多示例,但它们要么是针对以前版本的 MVC,要么没有使用其他版本的显示名称属性。
以下是我目前所拥有的。我已经设法通过服务器端 IsValid(...)
方法中的 Display
属性获取显示名称,但我不知道如何为客户端 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));
}
}
通常我在休息后自己解决了这个问题,只是把它留在这里以防它帮助其他人(或者有更好的解决方案):
public void AddValidation(ClientModelValidationContext context)
{
context.Attributes.Add("data-val", "true");
string otherName =
context.ModelMetadata.ContainerMetadata.Properties
.Single(p => p.PropertyName == this.OtherProperty)
.GetDisplayName();
context.Attributes.Add("data-val-notequalto",
string.Format(defaultErrorMessage, context.ModelMetadata.GetDisplayName(), otherName)
);
}
您可以通过 ClientModelValidationContext.ModelMetadata.ContainerMetadata.Properties