ASP.NET MVC ValidationAttribute获取其他属性显示名称

Nic*_*sen 7 validation asp.net-mvc client-side-validation validationattribute

我通过复制ASP.NET MVC 3 CompareAttribute创建了一个自定义CompareLessThan验证属性,而不是检查是否相等,我检查一个属性是否小于另一个属性.如果存在客户端错误,则向用户显示消息"{0}必须小于{1}".

我的模型设置如下,Display属性引用资源文件.

[CompareLessThan("AmountAvailable", ErrorMessageResourceName="CompareLessThan", ErrorMessageResourceType = typeof(Resources.ValidationMessages))]
[Display(Name = "Amount", ResourceType = typeof(Resources.Labels))]
public decimal Amount { get; set; }

[Display(Name = "AmountAvailable", ResourceType = typeof(Resources.Labels))]
public decimal AmountAvailable { get; set; }
Run Code Online (Sandbox Code Playgroud)

然后自定义验证GetClientValidationRules方法与CompareAttribute完全相同

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{            
    yield return new ModelClientValidationLessThanRule(FormatErrorMessage(metadata.DisplayName), FormatPropertyForClientValidation(OtherProperty), this.AllowEquality);
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们生成错误消息,如果出现问题,将显示给用户.我可以从资源文件中获取使用我的自定义CompareLessThan属性修饰的属性的显示名称,但我的问题是如何获取我们正在比较的"其他"属性的显示名称?在IsValid方法中,我们引用了validationContext,我可以从中为'other'属性生成PropertyInfo对象,我想获取显示名称.但是,在GetClientValidationRules中,我没有访问权限.

我总是可以为另一个属性的显示名称传递另一个值,但我希望有一种方法可以派生它,因为我已经用数据注释指定它.

有任何想法吗?

Len*_*rri 7

从ASP.NET MVC 4开始,这就是我设法获得其他属性的方法:

PropertyInfo otherPropertyInfo =
                  this.Metadata.ContainerType.GetProperty(attribute.DependentProperty);
Run Code Online (Sandbox Code Playgroud)

然后我Display attribute从酒店得到了:

var displayAttribute =
    otherPropertyInfo.GetCustomAttributes(typeof(DisplayAttribute), true).
    FirstOrDefault() as DisplayProperty;
Run Code Online (Sandbox Code Playgroud)

在你的情况下:

// GetName() is important to get the translated name if you're using a resource file...
this.otherPropertyDisplayName = displayAttribute.GetName();
Run Code Online (Sandbox Code Playgroud)

GetName() 参考:

http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.displayattribute.name%28v=vs.95%29.aspx


Nic*_*sen 5

nemesv提供的答案不起作用,因为metadata.Model属性的值为0.但是,通过元数据,我们确实拥有模型的全名,因此可以创建该模型的新实例,然后创建来自该创建实例的新DataAnnonationsModelMetadataProvider.从那里我们可以得到另一个属性的显示名称.

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
    Type type = Type.GetType(metadata.ContainerType.FullName);
    var model = Activator.CreateInstance(type);

    var provider = new DataAnnotationsModelMetadataProvider();
    var otherMetaData = provider.GetMetadataForProperty(() => model, type, this.OtherProperty);

    this.otherPropertyDisplayName = otherMetaData.DisplayName;

    yield return new ModelClientValidationLessThanRule(FormatErrorMessage(metadata.DisplayName), FormatPropertyForClientValidation(this.OtherProperty), this.AllowEquality);
}
Run Code Online (Sandbox Code Playgroud)

我真的不喜欢这个解决方案(即使它有效),因为它似乎应该有更好的方法.还有其他人有其他想法吗?