想知道为什么在重写的属性上的LabelFor中忽略DisplayName属性

时间:2010-03-31 19:07:46

标签: validation asp.net-mvc-2 attributes

今天我在ASP.NET MVC 2中使用<%=Html.LabelFor(m=>m.MyProperty)%>中的[DisplayName("Show this instead of MyProperty")]属性并使用System.ComponentModel中的[Required]属性时感到困惑。

事实证明,当我将属性放在重写属性上时,LabelFor似乎没有注意到它。
但是,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; } } 属性在重写的属性上工作正常,生成的errormessage实际上使用DisplayNameAttribute。

这是一些简单的示例代码,更现实的情况是我有一个与viewmodel分开的databasemodel,但为了方便起见,我想继承databasemodel,添加View-only属性并使用属性装饰viewmodel用户界面。

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> 包含:

    [HttpPost]
    public ActionResult Edit(EditModel model)
    {
        if (!ModelState.IsValid)
            return View(model);
        return View("Thanks");
    }

然后标签显示为“PleaseOverrideMe”使用DisplayNameAttribute)和“此属性仅存在于EditModel”(<查看页面时强>使用 DisplayNameAttribute 如果我使用空值发布,则使用此ActionMethod触发验证:

<%= Html.ValidationMessageFor(model => model.PleaseOverrideMe) %>

[DisplayName("This should be as label for please override me!")]实际上使用{{1}}属性,并生成默认的errortext “这应该是标签,请覆盖我!字段是必需的。”

有些友好的灵魂会对此有所了解吗?

5 个答案:

答案 0 :(得分:12)

Model binding and metadata using the strongly-typed helpers looks at the declared, rather than the runtime, type of the model。我认为这是一个错误,但显然MVC团队不同意我,因为我的Connect问题被关闭为“按设计。”

答案 1 :(得分:11)

我使用[DisplayName(“Profile Name”)]遇到了这个问题,而是使用了[Display(Name = "Profile Name")]来解决我的问题。我不确定这是否有用。

前者来自System.ComponentModel而前者来自System.ComponentModel.DataAnnotations

答案 2 :(得分:3)

当我有一个强类型的部分视图接口时,我遇到了同样的问题。接口定义了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"-->

答案 3 :(得分: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 :(得分:3)

在我的情况下,我忘记了通过使用getter和setter使它成为一个属性。 而不是

public string CompanyName;

我应该用

public string CompanyName {get;set;}