web-dev-qa-db-ja.com

Entity Framework 4.0でのSystem.ComponentModel.DataAnnotationsの使用

私はMVC3を使用しており、モデルとしてEntity Framework 4.0エンティティを使用しています。これまでのところ、それをモデルとして使用する限り、すべてがうまく機能します(すべてのクラッド操作/ページ生成はそのままで機能します)。しかし、手動でモデルを生成する場合と同じように、堅牢なラベルと検証情報をどのようにして取得するのでしょうか。

これが私の意味の例です。これは、サンプル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>}

enter image description here

私の質問は: EF4を使用して生成されたエンティティにこれらの追加の装飾を追加するにはどうすればよいですか? System.ComponentModel.DataAnnotations以外に使用する必要があるものはありますか?私はエンティティが再生成されることを知っています。これをエンティティのコードに直接追加することはおそらくお勧めできませんが、何らかの理由で、ビューにラベルテキストを手動で入力するよりも優れたアプローチを考えることができません(不完全な、理由はありません)これを行う必要があります。これはMVCです!)。アプリケーションを動的にして、モデルの正しい表示情報を取得し、MVCアプローチを維持できるようにしたいと考えています。どうすればいいのですか?

52
Ryan Hayes

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;
}
80
Austin Lamb

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;

            //...
        }
    }
}
1
Carter Medlin

上記と同じですが、すべての詳細があり、機能します

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
Arun Prasad E S