Как установить свойство 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()
}