7

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

我的模型设置如下,显示属性引用资源文件。

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

那么自定义验证GetClientValidationRules方法和CompareAttribute中的方法一模一样

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

在这里,我们正在生成错误消息,如果出现问题,将向用户显示。我可以从用我的自定义 CompareLessThan 属性装饰的属性的资源文件中获取显示名称,但我的问题是如何获取我们正在比较的“其他”属性的显示名称?在 IsValid 方法中,我们有一个对 validationContext 的引用,我可以从中为“其他”属性生成一个 PropertyInfo 对象,并且我认为可以获取显示名称。但是,在 GetClientValidationRules 中我无权访问它。

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

有任何想法吗?

4

3 回答 3

7

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

PropertyInfo otherPropertyInfo =
                  this.Metadata.ContainerType.GetProperty(attribute.DependentProperty);

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

var displayAttribute =
    otherPropertyInfo.GetCustomAttributes(typeof(DisplayAttribute), true).
    FirstOrDefault() as DisplayProperty;

在你的情况下:

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

GetName()参考:

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

于 2012-06-25T21:11:04.223 回答
6

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

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

于 2011-10-14T18:13:21.420 回答
4

我还没有尝试过,但是您可以使用该属性获取模型metadata.Properties属性

metadata.Properties.Single(p => p.PropertyName == "OtherPropName").DisplayName;

编辑:因为属性是空的,你总是可以做的(虽然它很优雅)。您可以自己生成元数据。

var provider = new DataAnnotationsModelMetadataProvider();
var otherMetaData = provider.GetMetadataForProperty(() => metaData.Model, metaData.ModelType, "OtherPropertyName");
于 2011-10-14T05:11:20.643 回答