Использование System.ComponentModel.DataAnnotations с Entity Framework 4.0

Я работаю с MVC3 и использую Entity Framework 4.0 Entities в качестве моей модели. До сих пор все отлично работает, поскольку используется в качестве модели (все операции 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>}

enter image description here

Мой вопрос: Как добавить эти дополнительные украшения к сущностям, которые сгенерированы с использованием EF4? Есть ли что-то помимо System.ComponentModel.DataAnnotations, которые я должен использовать? Я знаю, что объекты получаются регенерированными, и, вероятно, не рекомендуется добавлять это в код сущности напрямую, но по какой-то причине я не могу придумать более подходящий подход, чем вручную ввести текст метки в представлении (lame, нет причин для должны сделать это, это MVC!). Я хочу сохранить его таким образом, чтобы приложение было достаточно динамичным, чтобы иметь возможность отображать правильную отображаемую информацию для моей модели и поддерживать подход MVC. Как это сделать?

Ответ 1

Я не делал этого для ASP.NET MVC (только для Silverlight), но я считаю, что будут применяться те же принципы. Вы можете создать "класс друзей метаданных", как показано ниже, потому что типы, сгенерированные EF, должны быть частичными, поэтому вы можете добавить к ним немного больше (например, атрибут MetadataTypeAttribute), а затем вы создадите этот родственный класс, содержащий метаданные.

Это вроде уродливо, но должно работать. Это происходит примерно так (предполагая, что объект EF называется "Person" ):

[MetadataType(typeof(PersonMetadata))]
public partial class Person { 
  // Note this class has nothing in it.  It 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;
}

Ответ 2

То же, что и выше, но со всеми подробностями и работает

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

И вот код

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

Ответ 3

Как и Остин Лэмб, но вместо этого, MetaData класс 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;

            //...
        }
    }
}

Ответ 4

Хорошая идея - вложить класс метаданных в частичный класс, но, к сожалению, Entity Framework всегда перезапишет его... Я работаю над MVC5, и первое решение поместить его в ту же папку, но отдельный класс работает нормально