2010-03-31 119 views
17

在做ASP.NET MVC 2几个<%=Html.LabelFor(m=>m.MyProperty)%>和使用[DisplayName("Show this instead of MyProperty")]属性从System.ComponentModel当我弄糊涂了。奇怪,为什么displayName属性为LabelFor忽略上覆盖的属性今天

事实证明,当我将属性放在重写的属性上时,LabelFor似乎没有注意到它。
但是,[Required]属性对重写的属性正常工作,生成的errormessage实际上使用DisplayNameAttribute。

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

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 的”这应该是作为标签,请忽略我的场!需要。”

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

+0

拉塞,你不得不在此期间任何运气? – 2010-09-02 13:31:27

+0

如果您使用反射来显示所有属性,则可以使用“ModelMetadata”类型。基本上你会这样做'Html.Label(prop.GetDisplayName())'。 – 2013-08-27 20:58:53

回答

11

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

+4

那么,我会尝试将它作为一个bug @ Connect提交,然后为“By Design”做好准备。 谢谢! – 2010-04-04 21:01:00

+0

不是一个错误?我将整个项目移到了MVC 3,这让我很痛苦。它曾经工作得很好 - DisplayName属性现在不应该这样工作吗? – Jack 2010-09-18 14:27:42

+0

那么当你重载编辑/显示对象模板并使用'Html.EditorForModel'时会发生什么?在你的模板中你使用'Html.Label()',你不能得到Display属性。按设计?他们是否雇用IE团队的白痴? – 2013-08-27 20:51:28

2

我有一个相同的问题,当我有一个局部视图强类型的接口。该接口定义了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"--> 
11

我跑进使用[DisplayName的(“配置文件名称”)]这个问题,并用来代替[Display(Name = "Profile Name")]其固定在我的情况的问题。我不确定这是否有用。

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

+3

六年后,这个问题在MVC 5中修复了同样的问题:) – pmbanka 2016-02-16 15:59:55

+1

+七。固定在核心mvc *大拇指* – 2017-01-26 11:16:56

3

好吧,我似乎找到了一个解决方法,如果你不使用必需的标签!只需使用正则表达式或长度属性来确定是否存在有效的条目。希望这会有所帮助,虽然有点晚。

[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

在我的情况下,我被遗忘了使用getter和setters使它成为一个属性。 而不是

public string CompanyName; 

我应该用

public string CompanyName {get;set;}