从验证属性中检索模型MetaData

时间:2013-07-22 15:25:39

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

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

具体而言,检查该物业是否附有UppercaseAttribute;如果是这种情况,那么它将执行不同的逻辑路径。如果可以从ModelMetadata中抓取ValidationAttribute,我将使用以下代码进行检查:

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

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

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

2 个答案:

答案 0 :(得分:4)

以下是您可以做的事情:

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,因此您必须根据其显示名称获取属性名称。

答案 1 :(得分:3)

回答你的第一个问题:是的。您可以访问ModelMetadata对象中的ValidationAttribute对象。最简单的方法是实现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;         
        }
    }