我正在使用MVC3,并使用Entity Framework 4.0实体作为我的模型。到目前为止,就使用它作为模型而言,一切都很有效(所有的crud操作/页面生成开箱即用)。我想知道,你如何获得与手动生成模型时相同的强大标签和验证信息?
这是我的意思的一个例子。这是由MVC3示例项目生成的类:
public class LogOnModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
通过上面的示例,您可以指定在字段的标签中显示的内容(显示)以及要使用的字段类型(密码)。但是,当我尝试使用实体框架并将其推送到下面的视图时,我看到自动生成的标签只是字段名称,而不是我希望用户看到/必须阅读的任何内容:
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Person</legend>
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.MiddleName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.MiddleName)
@Html.ValidationMessageFor(model => model.MiddleName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Birthdate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Birthdate)
@Html.ValidationMessageFor(model => model.Birthdate)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>}
我的问题是:如何将这些额外的装饰添加到使用EF4生成的实体中?除了我应该使用的System.ComponentModel.DataAnnotations之外还有什么东西吗?我知道实体会重新生成,直接将它添加到实体代码可能不是一个好主意,但由于某种原因,我想不出比在视图中手动输入标签文本更好的方法(跛脚,没有理由必须这样做,这是MVC!)。我想保留它,以便应用程序足够动态,能够为我的模型提供正确的显示信息并保持MVC方法。我该怎么做?
答案 0 :(得分:79)
我没有为ASP.NET MVC做过这个(仅适用于Silverlight),但我相信同样的原则也适用。您可以创建一个“元数据伙伴类”,如下所示,因为EF生成的类型应该是部分的,因此您可以向它们添加更多内容(如MetadataTypeAttribute),然后创建这个包含元数据的兄弟类。
这有点难看,但应该有用。它是这样的(假设EF实体名为“Person”):
[MetadataType(typeof(PersonMetadata))]
public partial class Person {
// Note this class has nothing in it. It's just here to add the class-level attribute.
}
public class PersonMetadata {
// Name the field the same as EF named the property - "FirstName" for example.
// Also, the type needs to match. Basically just redeclare it.
// Note that this is a field. I think it can be a property too, but fields definitely should work.
[Required]
[Display(Name = "First Name")]
public string FirstName;
}
答案 1 :(得分:1)
与上述相同,但包含所有细节,并且有效
以下是代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace Validate.Models
{
[MetadataType(typeof(PersonMetadata))]
public partial class Person
{
// Note this class has nothing in it. It's just here to add the class-level attribute.
}
public class PersonMetadata
{
// Name the field the same as EF named the property - "FirstName" for example.
// Also, the type needs to match. Basically just redeclare it.
// Note that this is a field. I think it can be a property too, but fields definitely should work.
[Required]
[Display(Name = "Enter Your Name")]
public string FirstName;
}
}
答案 2 :(得分:1)
喜欢 Austin Lamb 的答案,而是将MetaData
类嵌套在实体类中,从而减少公共命名空间列表中的类数量,并且无需每个元数据类都有一个唯一的名称。
using System.ComponentModel.DataAnnotations;
namespace Validate.Models
{
[MetadataType(typeof(MetaData))]
public partial class Person
{
public class MetaData
{
[Required]
[Display(Name = "Enter Your Name")]
public string FirstName;
//...
}
}
}