今天我在做几个 <%=Html.LabelFor(m=>m.MyProperty)%>
时感到困惑在 ASP.NET MVC 2 中并使用 [DisplayName("Show this instead of MyProperty")]
来自 System.ComponentModel
的属性.
事实证明,当我将属性放在被覆盖的属性上时,LabelFor 似乎没有注意到它。
但是,[Required]
属性在被覆盖的属性上工作正常,并且生成的错误消息实际上使用了 DisplayNameAttribute。
这是一些简单的示例代码,更现实的情况是我有一个与 View 模型分开的数据库模型,但为了方便起见,我想从数据库模型继承,添加仅查看属性并用 UI 的属性装饰 View 模型.
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!")]
属性,并产生默认的错误文本“这应该是标签,请覆盖我!字段是必需的。”一些友好的灵魂会对此有所了解吗?
最佳答案
当我有一个对界面进行强类型化的局部 View 时,我遇到了同样的问题。该接口(interface)定义了 DisplayName
并且实现该接口(interface)的类试图覆盖它。我发现让它尊重覆盖的唯一方法是输入实现类。我不得不更改 View 的模型类型或强制转换。不幸的是,这完全否定了使用接口(interface)作为模型类型的好处。我猜我最终会为每个实现类得到某种程度的重复 View 标记,而不是在强类型的“帮助器”中进行转换。
在这种类型的解决方法甚至是远程有用的远程机会(没有让我抱有希望),这里有一个例子。对于尝试覆盖名称的所有可能的实现类,肯定有一些方法可以处理这个问题,但它肯定比它应该的更麻烦。
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"-->
关于validation - 想知道为什么在覆盖属性的 LabelFor 中忽略 DisplayName 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2555759/