【问题标题】:Retrieving Model MetaData from within a validation attribute从验证属性中检索模型元数据
【发布时间】:2013-07-21 10:02:10
【问题描述】:

使用 MVC4,我需要从自定义 ValidationAttribute 中检索当前的 ModelMetadata。这样做的原因是验证属性需要知道哪些其他属性附加到正在验证的特定属性。

特别是检查该属性是否附加了UppercaseAttribute;如果是这种情况,那么它将执行不同的逻辑路径。如果可以从ValidationAttribute 中获取ModelMetadata,我将使用以下代码进行检查:

ModelMetadata.ContainerType
    .GetProperty(ViewData.ModelMetadata.PropertyName)
    .GetCustomAttributes(typeof(UppercaseAttribute), true)

首先,是否可以从自定义ValidationAttribute 中检索ModelMetadata

其次,上面的代码是检查属性是否附加了特定属性的最佳实践。

【问题讨论】:

  • 您是否需要此验证属性仅用于特定模型?如果是这样,您可以发布您的模型吗?

标签: c# .net validation asp.net-mvc-4


【解决方案1】:

你可以这样做:

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    var model = validationContext.ObjectInstance;

    var displayName = validationContext.DisplayName;
    var propertyName = model.GetType().GetProperties()
        .Where(p => p.GetCustomAttributes(false).OfType<DisplayAttribute>().Any(a => a.Name == displayName))
        .Select(p => p.Name).FirstOrDefault();
    if (propertyName == null)
        propertyName = displayName;

    var property = model.GetType().GetProperty(propertyName);
    var uppercaseAttribute = property.GetCustomAttributes(typeof(UppercaseAttribute), false).SingleOrDefault() as UppercaseAttribute;

    if (uppercaseAttribute != null)
    {
        // some code...
    }

    // return validation result...
}

由于某种原因,validationContext.MemberName 始终为 null,因此您必须根据其显示名称获取属性名称。

【讨论】:

  • 太棒了!这几乎是我要去的地方,除了由于validationContext.MemberName 为null,我对如何获取属性名称感到困惑。我猜如果显示名称为空,那么它将默认为属性名称?
  • 是的,如果没有显示名称,validationContext.DisplayName 返回属性名称。我的答案中代码的唯一问题是,如果两个属性具有相同的显示名称,它将不起作用,但通常情况并非如此。
  • 是的,我确实注意到了这一点,但我想不出在我的代码中会发生这种情况的场景..
【解决方案2】:

回答你的第一个问题:是的。您可以在ValidationAttribute 对象中访问ModelMetadata 对象。最简单的方法是实现System.Web.Mvc.IMetadataAware 接口。该接口有一个称为OnMetadataCreated 的方法,它将在验证属性对象上的IsValid 方法之前调用。此方法用于接收当前的 ModelMetadata 对象。下面的代码演示了用法:

   public class MyCustomValidationAttribute : ValidationAttribute, IMetadataAware
    {
        private readonly object _typeId = new object();
        private ModelMetadata _metadata;

        public MyCustomValidationAttribute()
        {
        }

        public override object TypeId
        {
            get
            {
                return _typeId;
            }
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            //Do something with the meta data
            string propertyName = _metadata.PropertyName;

            return ValidationResult.Success;
        }

        public void OnMetadataCreated(ModelMetadata metadata)
        {
            _metadata = metadata;         
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-14
    相关资源
    最近更新 更多