MVC et Entity Framework Html.DisplayNameFor avec un modèle Composite

je suis assez à l'aise avec MVVM en utilisant WPF/Silverlight mais c'est ma première tentative à une Application web MVC...juste une info pour mon arrière-plan.

j'ai créé un controller appelé TestSitesController qui a été généré automatiquement à partir de la classe model "Site" dans mon Model Framework Entity (le template qui génère les actions et les vues en lecture/écriture). La seule chose que j'ai modifiée était dans 3 spots il y avait un paramètre par défaut de Guid id = null pour certaines méthodes. Je viens de me débarrasser de l' "= null" tout fonctionne très bien. Voici un exemple de ce que j'ai changé

public ActionResult Delete(Guid id = null)
{
    //....
}

c'est Ce qui a été changé pour

public ActionResult Delete(Guid id)
{
    //....
}

le modèle de Site n'est rien de spécial SiteId, Abréviation, et DisplayName...essayant de garder aussi simple que possible pour cette question. Ok donc je dirige le site web et goto htpp://.../ TestSites / et tout fonctionne parfaitement.

j'ai remarqué que toutes mes vues (Create, Delete, Details et Edit) utilisent un mvcweb @model.Mesentités.Site ce qui me convient parfaitement pour l'instant, mais dans L'Index.vue cshtml j'ai remarqué qu'il utilisait un

@model IEnumerable<MVCWeb.MyEntities.Site>

cela fonctionne très bien pour le modèle généré mais je voudrais utiliser un "modèle de vue Composite" et peut-être que c'est là que j'essaie de mélanger mes connaissances MVVM mais que je m'en tiendrais à cela si possible. Dans mon esprit un modèle de vue Composite est juste un modèle qui est spécifique vers une vue qui est composé de 1 ou plusieurs modèles D'entités avec des propriétés supplémentaires comme SelectedSiteId, etc.

alors j'ai créé un très simple ViewModel appelé TestSitesViewModel

public class TestSitesViewModel
{
    //Eventually this will be added to a base ViewModel to get rid
    //of the ViewBag dependencies
    [Display(Name = "Web Page Title")]
    public string WebPageTitle;

    public IEnumerable<MVCWeb.MyEntities.Site> Sites;

    //Other Entities, IEnumberables, or properties go here
    //Not important for this example
}

puis dans mon contrôleur j'ai ajouté une méthode D'action appelée IndexWithViewModel

public ActionResult IndexWithViewModel()
{
    var vm = new TestSitesViewModel();
    vm.WebPageTitle = "Sites With Composite View Model";
    vm.Sites = db.Sites.ToList();

    return View(vm);
}

j'ai alors fait une copie de L'Index.cshtml et l'a nommé IndexWithModel.CSHTML pour correspondre à mon nouveau nom de méthode ActionResult. J'ai changé la ligne supérieure de l'

@model IEnumerable<MVCWeb.MyEntities.Site>

@model MVCWeb.Models.TestSitesViewModel

j'ai ajouté ceci avant la section de table pour tester DisplayNameFor et le DisplayFor

@Html.DisplayNameFor(model => model.WebPageTitle)
&nbsp;
@Html.DisplayFor(model => model.WebPageTitle)
<br />

changé le

@foreach (var item in Model) {

@foreach (var item in Model.Sites) {

et a commenté la section tr qui contient tous les en-têtes de table pour le moment. Tout fonctionne parfaitement sauf que le @Html.DisplayNameFor affiche le nom de la variable "WebPageTitle" au lieu d'utiliser "Web Page Title" comme indiqué dans l'attribut Display de L'Annotation des données dans

[Display(Name = "Web Page Title")]
public string WebPageTitle;

aussi si je commente en arrière dans le tr section qui contient les informations d'en-tête de table. Je ne peux pas pour la vie de moi trouver ce qu'il faut mettre dans j'ai essayé le modèle.Site.Abréviation, modèle.Sites[0].Abréviation, et diverses autres combinaisons mais obtenir des erreurs.

<tr>
    <th>
        @Html.DisplayNameFor(model => model.Abbreviation)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.DisplayName)
    </th>
    <th></th>
</tr>

alors qu'est-ce que je devrais y utiliser? Je ne suis pas tout à fait sûr pourquoi modèle.Site.L'abréviation ne fonctionne pas car les Sites est le même type exact qui a été utilisé que le modèle dans L'Index original.cshtml

17
demandé sur Dan P 2013-04-12 20:35:49

2 réponses

j'ai enfin compris ce après déconner pendant plusieurs heures.

1er problème pour utiliser l'Écran arrtibute dans les Données Anotations un get et set acessor méthodes doit être ajoutée, même si elles ne sont que celles par défaut. Je suppose que c'est parce qu'ils doivent travailler uniquement sur les propriétés, et non les données membres d'une classe. Voici le code pour obtenir l'

@Html.DisplayNameFor(model => model.WebPageTitle)

fonctionne correctement

public class TestSitesViewModel
{
    //Eventually this will be added to a base ViewModel to get rid of
    //the ViewBag dependencies
    [Display(Name = "Web Page Title")]
    public string WebPageTitle { get; set; }

    //PUBLIC DATA MEMBER WON'T WORK
    //IT NEEDS TO BE PROPERTY AS DECLARED ABOVE
    //public string WebPageTitle;

    public IEnumerable<MVCWeb.MyEntities.Site> Sites;

    //Other Entities, IEnumberables, or properties go here
    //Not important for this example
}

2ème partie du problème était l'accès aux Métadonnées dans une variable innombrables. J'ai déclaré la variable temporaire headerMetadata et je l'ai utilisée au lieu d'essayer d'accéder aux propriétés par l'intermédiaire de l'IEnumerable

@{var headerMetadata = Model.Sites.FirstOrDefault();}
<tr>
    <th>            
        @Html.DisplayNameFor(model => headerMetadata.Abbreviation)
    </th>
    <th>
        @Html.DisplayNameFor(model => headerMetadata.DisplayName)
    </th>
    ...

cela pose la question de savoir quand la variable headerMetadata sort du champ d'application? Est-il disponible pour l'ensemble de la vue ou est-il limité aux balises html table? Je suppose que c'est une autre question pour un autre rendez-vous.

20
répondu Dan P 2013-04-12 20:18:24

je vais tenter ma chance avec mon nouveau MVVM ASP.NET expérience MVC.

au lieu d'appeler @Html.DisplayNameFor(model => model.WebPageTitle), essayez d'utiliser @Html.DisplayFor(model => model.WebPageTitle). Vous semblez définir la valeur WebPageTitle dans votre IndexWithViewModel controller qui devrait apparaître dans votre vue.

partage modèles pour ASP.NET MVC. Vous pouvez configurer des modèles personnalisés ou des partiels pour DisplayFor / EditorFor helpers à /Views/Shared/EditorTemplates/Site.cshtml et /Views/Shared/DisplayTemplates/Site.cshtml. ASP.NET MVC va automatiquement ramasser sur les templates lors du rendu de l'objet de votre Site avec DisplayFor et EditorFor.

Bonne chance!

1
répondu Brett 2017-05-23 12:32:47