Интересно, почему атрибут DisplayName игнорируется в LabelFor для переопределенного свойства - PullRequest
19 голосов
/ 31 марта 2010

сегодня я запутался, когда делал пару <%=Html.LabelFor(m=>m.MyProperty)%> в ASP.NET MVC 2 и использовал атрибут [DisplayName("Show this instead of MyProperty")] из System.ComponentModel.

Как оказалось, когда я помещал атрибут в переопределенное свойство, LabelFor, похоже, не замечал этого.
Однако атрибут [Required] отлично работает с переопределенным свойством, и сгенерированное сообщение об ошибке фактически использует атрибут DisplayNameAttribute.

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

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!")] и выдает текст ошибки по умолчанию "Это поле должно быть как метка для поля" Пожалуйста, переопределите меня! "Обязательно."

Может ли какая-нибудь дружелюбная душа пролить свет на это?

Ответы [ 5 ]

12 голосов
/ 01 апреля 2010

Привязка модели и метаданные с использованием строго типизированных помощников рассматривают объявленный, а не исполняемый тип модели . Я считаю это ошибкой, но, очевидно, команда MVC не согласна со мной, так как моя проблема с Connect была закрыта как «By Design».

11 голосов
/ 05 ноября 2010

Я столкнулся с этой проблемой, используя [DisplayName ("Имя профиля")], и вместо этого использовал [Display(Name = "Profile Name")], что решило проблему в моем случае. Я не уверен, будет ли это полезно.

Первый из System.ComponentModel, а второй из System.ComponentModel.DataAnnotations.

3 голосов
/ 15 сентября 2014

В моем случае я забыл сделать его свойством, используя методы получения и установки. Вместо

public string CompanyName;

Я должен был использовать

public string CompanyName {get;set;}
3 голосов
/ 24 марта 2011

Хорошо, похоже, я нашел обходной путь, если вы не используете с ним тег Обязательный! просто используйте регулярное выражение или атрибут длины, чтобы определить, существует ли допустимая запись. Надеюсь, это поможет, хотя уже немного поздно.

[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; }

Все еще работает.

3 голосов
/ 27 апреля 2010

У меня была такая же проблема, когда у меня было строго типизированное представление интерфейса. Интерфейс определил 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"-->
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...