web-dev-qa-db-fra.com

Utilisation de System.ComponentModel.DataAnnotations avec Entity Framework 4.0

Je travaille avec MVC3 et j'utilise Entity Framework 4.0 Entities comme modèle. Jusqu'à présent, tout fonctionne parfaitement pour l'utiliser comme modèle (toutes les opérations crud/générations de page fonctionnent prêtes à l'emploi). Je me demande cependant comment obtenir les mêmes étiquettes robustes et informations de validation que lorsque vous générez un modèle manuellement.

Voici un exemple de ce que je veux dire. Ceci est une classe générée par l'exemple de projet 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; }
}

Avec l'exemple ci-dessus, vous pouvez spécifier ce qui sera rendu dans une étiquette pour le champ (Afficher) et quel type de champ utiliser (Mot de passe). Cependant, lorsque j'essaie d'utiliser le cadre de l'entité et de l'afficher dans la vue ci-dessous, je constate que les étiquettes générées automatiquement ne sont que les noms de champs, et pas ce que je veux que l'utilisateur voie/doive lire:

@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

Ma question est la suivante: Comment puis-je ajouter ces décorations supplémentaires aux entités générées à l'aide de EF4? Existe-t-il autre chose que System.ComponentModel.DataAnnotations que je devrais utiliser? Je sais que les entités sont régénérées et ce n'est probablement pas une bonne idée d'ajouter cela directement au code des entités, mais pour une raison quelconque, je ne peux pas penser à une meilleure approche que de saisir manuellement le texte de l'étiquette dans la vue (boiteux, il n'y a aucune raison de le faire. faire cela, c’est MVC!). Je souhaite le conserver de manière à ce que l'application soit suffisamment dynamique pour pouvoir obtenir les informations d'affichage correctes pour mon modèle et conserver une approche MVC. Comment fait-on ça?

50
Ryan Hayes

Je n'ai pas fait cela pour ASP.NET MVC (uniquement pour Silverlight) mais je pense que les mêmes principes s'appliqueraient. Vous pouvez créer une "classe de métadonnées" comme ci-dessous, car les types générés par EF doivent être partiels. Vous pouvez donc en ajouter un peu plus (comme MetadataTypeAttribute), puis vous créez cette classe soeur qui contient les métadonnées.

C'est un peu moche, mais ça devrait marcher. Cela ressemble à ceci (en supposant que l'entité EF est nommée "Personne"):

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

Comme ci-dessus mais avec tous les détails, et ça marche 

 enter image description here

 enter image description here

 enter image description here

 enter image description here

Et voici le code

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

Comme la réponse de Austin Lamb, mais en imbriquant la classe MetaData dans la classe d'entité, réduisant ainsi le nombre de classes dans votre liste d'espaces de noms publics et éliminant le besoin de donner un nom unique à chaque classe de métadonnées.

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;

            //...
        }
    }
}
0
Carter Medlin