Как установить свойство Description для ModelMetadata

Я поместил атрибут Description в свое свойство, но свойство Description в ModelMetada в любом случае равно нулю.

[Description("sss")]
public int Id { get; set; }

Кстати I've putted Corect?

РЕДАКТИРОВАТЬ

Я посмотрел на источник MVC. Это не похоже на ошибку. Атрибут decsription просто никогда не используется. В классе Metadata есть свойство, но это свойство никогда не устанавливается и не вызывается. У метода CreateMetadata нет кода для работы с атрибутом decription. Решением будет переопределение метода create, а также редактирование шаблонов.

4 ответа

Решение

Пытаясь найти способ заставить это работать, я наткнулся на сообщение в блоге, в котором говорилось, что ни Description, ни Watermark не могут использоваться с нынешним воплощением платформы DataAnnotations.

Я нашел обходной путь, который выглядит примерно так:

(Отказ от ответственности: этот код отредактирован из моей версии для компиляции, чтобы удалить его из провайдера метаданных, созданного с помощью композиции, поэтому он не может компилироваться напрямую без каких-либо исправлений.)

public class CustomDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<System.Attribute> attributes, System.Type containerType, System.Func<object> modelAccessor, System.Type modelType, string propertyName)
    {
        var baseModelMetadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        var result = new CustomMetadata(modelMetadataProvider, containerType, modelAccessor, modelType, propertyName, attributes.OfType<DisplayColumnAttribute>().FirstOrDefault(), attributes)
        {
            TemplateHint = !string.IsNullOrEmpty(templateName) ?                              templateName : baseModelMetaData.TemplateHint,
            HideSurroundingHtml = baseModelMetaData.HideSurroundingHtml,
            DataTypeName = baseModelMetaData.DataTypeName,
            IsReadOnly = baseModelMetaData.IsReadOnly,
            NullDisplayText = baseModelMetaData.NullDisplayText,
            DisplayFormatString = baseModelMetaData.DisplayFormatString,
            ConvertEmptyStringToNull = baseModelMetaData.ConvertEmptyStringToNull,
            EditFormatString = baseModelMetaData.EditFormatString,
            ShowForDisplay = baseModelMetaData.ShowForDisplay,
            ShowForEdit = baseModelMetaData.ShowForEdit,
            DisplayName = baseModelMetaData.DisplayName
        };
        return result;
    }
}

public class CustomMetadata : DataAnnotationsModelMetadata
{
    private string _description;

    public CustomMetadata(DataAnnotationsModelMetadataProvider provider, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName, DisplayColumnAttribute displayColumnAttribute, IEnumerable<Attribute> attributes)
            : base(provider, containerType, modelAccessor, modelType, propertyName, displayColumnAttribute)
        {
            var descAttr = attributes.OfType<DescriptionAttribute>().SingleOrDefault();
                    _description = descAttr != null ? descAttr.Description : "";
        }

        // here's the really important part
        public override string Description
        {
            get
            {
                return _description;
            }
            set
            {
                _description = value;
            }
        }
}

Затем в вашем Global.asax в Application_Start или везде, где вы регистрируете поставщиков метаданных модели:

ModelMetadataProviders.Current = new CustomMetadataProvider();

Это старый пост, но столкнулся с тем, что у него немного другое решение, чем у cfeduke. Я решил опубликовать это на случай, если кто-нибудь еще придет сюда.

По крайней мере, в MVC 3 вам не нужно определять пользовательский тип метаданных, просто поставщик. Читая исходный код MVC, метаданные строятся не из всех возможных атрибутов, только из нескольких:

DisplayAttribute обеспечивает:

  • Описание
  • ShortDisplayName
  • водяной знак
  • порядок

Атрибут DescriptionAttribute вообще не проверяется, поэтому, если он определен в вашей модели, метаданные будут отображаться как ноль. Если у вас есть проблемы с не заданными атрибутами метаданных, убедитесь, что провайдер действительно их читает.

class MyDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        var metaData = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);

        // Description - The default provider reads the description from DisplayAttribute.
        // Here we check for a description attribute as well.  This will overwrite anything
        // set before as we assume a Description attribute is more specific.
        DescriptionAttribute descriptionAttribute = attributes.OfType<DescriptionAttribute>().FirstOrDefault();
        if (descriptionAttribute != null)
        {
            metaData.Description = descriptionAttribute.Description;
        }

        return metaData;
    }
}

Правильный атрибут - DisplayNameAttribute. Вы можете сделать свой собственный атрибут, но он должен быть производным от DisplayNameAttribute.

Если вы используете MVC 3, вы можете использовать [AdditionalMetadata("AttributeName", "AttributeValue")] для пользовательских атрибутов.

В ваших методах расширения вы можете сделать что-то вроде:

if (ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).AdditionalValues.ContainsKey("AttributeName")) {    
 return ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).AdditionalValues["AttributeName"].ToString()    
}
Другие вопросы по тегам