Интересно, почему атрибут DisplayName игнорируется в LabelFor при переопределенном свойстве
Сегодня я запутался, когда делал пару <%=Html.LabelFor(m=>m.MyProperty)%>
в ASP.NET MVC 2 и использовал атрибут [DisplayName("Show this instead of MyProperty")]
из System.ComponentModel
.
Как оказалось, когда я помещал атрибут в переопределенное свойство, LabelFor, похоже, не заметил его.
Однако атрибут [Required]
отлично работает в переопределенном свойстве, и сгенерированный errormessage фактически использует DisplayNameAttribute.
Это какой-то тривиальный пример кода, более реалистичным сценарием является то, что у меня есть база данных данных отдельно от модели viewmodel, но для удобства я хотел бы наследовать из базы данных данных, добавлять свойства View-only и декорировать модель с атрибутами для пользовательского интерфейса.
public class POCOWithoutDataAnnotations
{
public virtual string PleaseOverrideMe { get; set; }
}
public class EditModel : POCOWithoutDataAnnotations
{
[Required]
[DisplayName("This should be as label for please override me!")]
public override string PleaseOverrideMe
{
get { return base.PleaseOverrideMe; }
set { base.PleaseOverrideMe = value; }
}
[Required]
[DisplayName("This property exists only in EditModel")]
public string NonOverriddenProp { get; set; }
}
Сильно типизированный ViewPage<EditModel>
содержит:
<div class="editor-label">
<%= Html.LabelFor(model => model.PleaseOverrideMe) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model.PleaseOverrideMe) %>
<%= Html.ValidationMessageFor(model => model.PleaseOverrideMe) %>
</div>
<div class="editor-label">
<%= Html.LabelFor(model => model.NonOverriddenProp) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model.NonOverriddenProp) %>
<%= Html.ValidationMessageFor(model => model.NonOverriddenProp) %>
</div>
Затем метки отображаются как "PleaseOverrideMe" ( не с использованием DisplayNameAttribute) и "Это свойство существует только в EditModel" ( с использованием DisplayNameAttribute) при просмотре страницы.
Если я отправляю пустые значения, запуская проверку с помощью этого ActionMethod:
[HttpPost]
public ActionResult Edit(EditModel model)
{
if (!ModelState.IsValid)
return View(model);
return View("Thanks");
}
<%= Html.ValidationMessageFor(model => model.PleaseOverrideMe) %>
на самом деле использует атрибут [DisplayName("This should be as label for please override me!")]
и создает по умолчанию errortext. "Это должно быть как метка для поля" пожалуйста, переопределите меня! ".
Может ли какая-нибудь дружеская душа пролить свет на это?
Ответы
Ответ 1
привязка модели и метаданные с использованием строго типизированных помощников рассматривает тип модели, объявленный, а не тип исполнения. Я считаю, что это ошибка, но, видимо, команда MVC не согласна со мной, так как моя проблема с Connect на этом была закрыта как "По дизайну".
Ответ 2
Я столкнулся с этой проблемой, используя [DisplayName ( "Имя профиля" )] и вместо этого использовал [Display(Name = "Profile Name")]
, который исправил проблему в моем случае. Я не уверен, что это было бы полезно.
Первый из System.ComponentModel
, а последний из System.ComponentModel.DataAnnotations
.
Ответ 3
Хорошо, я, похоже, нашел обходное решение, если вы не используете тег Required с ним! просто используйте атрибут регулярного выражения или длины, чтобы определить, существует ли допустимая запись. Надеюсь, это поможет, хотя и немного поздно.
[RegularExpression(@"^[1-9][0-9][0-9]$")] //validates that there is at least 1 in the quantity and no more than 999
[DisplayName("Quantity:")]
public string quantity { get; set; }
Все еще работает.
Ответ 4
В моем случае я был забыт сделать его собственностью, используя геттеры и сеттеры.
Вместо
public string CompanyName;
Я должен был использовать
public string CompanyName {get;set;}
Ответ 5
У меня была такая же проблема, когда у меня было частичное представление, строго типизированное для интерфейса. Интерфейс определил DisplayName
, а класс, который реализовал интерфейс, попытался переопределить его. Единственный способ, который я нашел, чтобы заставить его уважать переопределение, - это ввести класс реализации. Мне пришлось либо изменить тип модели просмотра, либо бросить. К сожалению, это полностью отрицает преимущества использования интерфейса в качестве типа модели. Я предполагаю, что у меня будет некоторый уровень дублированной разметки разметки для каждого класса реализации, в то время как не выполняется в пределах строго типизированных "помощников".
В отдаленном случае, что этот способ обхода даже отдаленно полезен (не доставляя надежды), вот пример. Конечно, есть способы работать с этим для всех возможных классов реализации, которые пытаются переопределить имя, но это определенно больше хлопот, чем должно быть.
public interface IAddressModel {
...
[DisplayName("Province")]
public string Province { get; set; }
...
}
public class UsAddressModel : IAddressModel {
...
[DisplayName("State")]
public string Province { get; set; }
...
}
<%= Html.LabelFor(m => m.State) %> <!--"Province"-->
<%= Html.LabelFor(m => (m as UsAddressModel).State) %> <!--"State"-->