将System.ComponentModel.DataAnnotations与Entity Framework 4.0一起使用

问题描述 投票:50回答:3

我正在使用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方法。我该怎么做?

asp.net-mvc asp.net-mvc-3 c#-4.0 entity-framework-4
3个回答
80
投票

我没有为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
投票

与上面相同,但有所有细节,它的工作原理

enter image description here

enter image description here

enter image description here

enter image description here

这是守则

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

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;

            //...
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.