ASP.NET MVC ValidationAttribute Получить другое отображаемое имя свойства - PullRequest
7 голосов
/ 14 октября 2011

Я создал собственный атрибут проверки CompareLessThan, скопировав ASP.NET MVC 3 CompareAttribute, и вместо проверки на равенство я проверяю, чтобы увидеть, что одно свойство меньше другого. Если имеется ошибка на стороне клиента, пользователю отображается сообщение «{0} должно быть меньше {1}».

Моя модель настроена следующим образом с атрибутами Display, ссылающимися на файл ресурсов.

[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, но у меня вопрос: как мне получить отображаемое имя свойства «other», с которым мы сравниваем? В методе IsValid у нас есть ссылка на validationContext, из которого я могу сгенерировать объект PropertyInfo для свойства 'other' и, думаю, получить отображаемое имя. Но в правилах GetClientValidation у меня нет доступа к этому.

Я всегда мог просто передать другое значение для отображаемого имени другого свойства, но я надеялся, что будет способ получить его, так как я уже указываю его с аннотациями данных.

Есть идеи?

Ответы [ 3 ]

7 голосов
/ 26 июня 2012

Начиная с 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

5 голосов
/ 14 октября 2011

Ответ, предоставленный 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);
}

Мне действительно не нравится это решение (даже если оно работает), так как кажется, что должен быть лучший способ.У кого-нибудь есть еще идеи?

4 голосов
/ 14 октября 2011

Я не пробовал, но вы можете получить свойства модели с помощью свойства metadata.Properties

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

РЕДАКТИРОВАТЬ: потому что свойства пустые, что вы всегда можете сделать (хотя это очень элегантно).Вы можете создать метаданные для себя.

var provider = new DataAnnotationsModelMetadataProvider();
var otherMetaData = provider.GetMetadataForProperty(() => metaData.Model, metaData.ModelType, "OtherPropertyName");
...