web-dev-qa-db-fra.com

Le modèle dynamique MVC Razor, 'objet' ne contient pas de définition pour 'PropertyName'

Utilisation de MVC 3 avec le moteur de vue Razor. J'ai cette vue:

@model dynamic
@{
    var products = (List<ListItemBaseModel>)Model.Products;
    var threshold = (int)(Model.Threshold ?? 1);
    var id = Guid.NewGuid().ToString();
}

Il est appelé depuis une autre vue en utilisant ce code:

@Html.Partial("PartialViewName", new { Products = Model, Threshold = 5 })

Dans les deux vues, lorsque je les corrige et regarde Model, il semble contenir le bon objet. Quand j'exécute le code, j'obtiens une erreur sur la ligne "var products =" en disant:

'objet' ne contient pas de définition pour 'Produits'

Quelqu'un peut-il m'expliquer pourquoi je reçois cette erreur? Encore une fois, lorsque je regarde l’objet Model en mode débogage, l’apparence est bonne (avec 2 propriétés: Produits et Seuil)

104
Ruud van Falier

Passez-vous une instance d'une classe anonyme en tant que modèle de vue? Je viens d'essayer ceci (modèle de vue dynamique en CSHTML) et j'ai la même erreur que lorsque vous utilisez une classe anonyme, mais cela fonctionne bien si je crée une classe nommée. J'ai cherché mais je n'ai pas vu cela documenté nulle part.

// error
return View(new { Foo = 1, Bar = "test" });

// worked
return View(new TestClass { Foo = 1, Bar = "test" });

EDIT # 1:

Selon David Ebbo , vous ne pouvez pas passer un type anonyme dans une vue typée dynamiquement car les types anonymes sont compilés sous la forme internal. Comme la vue CSHTML est compilée dans un assembly séparé, elle ne peut pas accéder aux propriétés du type anonyme.

EDIT # 2:

David Ebbo a édité son post avec cette clarification:

Remarque (22/12/2011): maintenant que MVC 3 prend directement en charge la dynamique, la technique ci-dessous n'est plus nécessaire. Ce billet est en fait ce qui a conduit à l’intégration de la fonctionnalité dans MVC!

149
Lucas

Sur .NET 4.0 Les types anonymes peuvent être facilement convertis en ExpandoObjects et tous les problèmes sont résolus avec le temps système de la conversion. Départ ici

40
Adaptabi

Cela n'a rien à voir avec les types anonymes ayant des propriétés internes

C'est parfaitement possible passer des types anonymes d'une vue à une vue partielle

J'ai rencontré le même problème aujourd'hui et il n'y avait rien (directement) à faire avec le problème du passage de types anonymes et de leurs propriétés inhérentes internal.

En tant que tel, en ce qui concerne la question des PO, la réponse de @Lucas n’est pas pertinente - même si la solution de contournement fonctionnera .

Dans la question des OP, un type anonyme est passé d’une vue de l’Assemblée X à un partiel de l’Assemblée X , donc le problème évoqué par David Ebbo sur le fait que les propriétés soient internes aux types anonymes est sans conséquence; les types compilés pour la vue, le type partiel et le type anonyme sont tous contenus dans le même assemblage.

Alors, qu'est-ce qui cause l'impossibilité soudaine de passer d'un type anonyme à une vue partielle?

Au moins dans mon Dans cette situation, j’ai découvert que c’était dû à ne autre vue du même dossier qui spécifie un type de modèle qui ne peut pas être résol. Les vues étant compilées au moment de l'exécution, il serait donc logique de penser qu'un échec lors de la compilation des vues signifierait également un échec lors de la compilation des types dynamiques et que le partiel recevrait simplement un object. Ce qui se passe n’est pas immédiatement évident, mais dans l’exemple spécifique (et le mien) des PO, c’est plus que probablement la cause du problème.

Il est intéressant de noter que si le type de modèle est correct mais qu'une autre partie de la vue ne compile pas, les types anonymes ne sont pas affectés de la même manière. Cela doit être dû à la façon dont Razor rompt la compilation dynamique des composants de la vue.

Une fois que vous avez corrigé la vue incriminée, reconstruisez l'ensemble de la solution ou nettoyez et reconstruisez le projet avant de vérifier s'il est corrigé.

Pour vous assurer de ne pas être à nouveau pris au dépourvu, vous pouvez activer la compilation au moment de la compilation de vos vues Razor en ajoutant ceci à votre fichier csproj:

<PropertyGroup>
    <MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>
25
joshcomley

Ajoutez la classe suivante n’importe où dans votre solution (utilisez l’espace de noms System pour qu’il soit prêt à être utilisé sans ajouter de référence) -

    namespace System
    {
        public static class ExpandoHelper
        {
            public static ExpandoObject ToExpando(this object anonymousObject)
            {
                IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
                IDictionary<string, object> expando = new ExpandoObject();
                foreach (var item in anonymousDictionary)
                    expando.Add(item);
                return (ExpandoObject)expando;
            }

        }
    }

Lorsque vous envoyez le modèle à la vue, convertissez-le en Expando:

    return View(new {x=4, y=6}.ToExpando());
9
Segev -CJ- Shmueli

Au lieu d'utiliser le type de modèle dynamic dans la vue partielle.

Vous pouvez appeler les attributs d'objet anonyme en utilisant @ViewData.Eval("foo") au lieu de @Model.foo.

Ensuite, vous pouvez supprimer @Model dynamic de la vue.

Je suis récemment tombé sur ce problème en passant certains attributs entre des vues pour l'intégration de Facebook Social Comments. Exemple de code:

Html.RenderPartial(@"Layouts/Partials/_Comments", new {currentUrl = Model.CurrentPage.GetAbsoluteUrl(), commentCount = 5 });

Ensuite, à mon avis, je viens d'avoir cette div:

<div class="fb-comments" data-href="@ViewData.Eval("currentUrl")" data-numposts="@ViewData.Eval("commentCount")" data-width="100%"></div>
4
JamesG

je ne suis pas sûr que vous obteniez cette erreur car vous n'implémentez pas la solution de contournement. J'ai eu la même erreur dans une vue partielle. la solution consistait simplement à nettoyer la construction et à la reconstruire. Si la syntaxe est correcte, le code devrait fonctionner, mais le moteur du rasoir peut ne pas mettre à jour correctement les modifications du code.

0
goran

J'ai travaillé autour de ce problème en utilisant un dictionnaire.

 @Html.Partial("_Partial", new Dictionary<string, string> { { "Key1", "Val1" }, { "Key2", "Val2" }, { "Key3", "Val3" } });
0
Gerade Geldenhuys