Das dynamische MVC Razor-Modell 'Objekt' enthält keine Definition für 'Eigenschaftsname'.


106

Verwenden von MVC 3 mit Razor View Engine. Ich habe diese Ansicht:

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

Es wird aus einer anderen Ansicht mit diesem Code aufgerufen:

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

In beiden Ansichten scheint es, wenn ich sie debugge und Model beobachte, das richtige Objekt zu enthalten. Wenn ich den Code ausführe, wird in der Zeile "var products =" ein Fehler angezeigt, der besagt:

'Objekt' enthält keine Definition für 'Produkte'

Kann mir jemand erklären, warum ich diesen Fehler bekomme? Wenn ich das Model-Objekt im Debugging-Modus betrachte, sieht es wieder in Ordnung aus (mit zwei Eigenschaften: Produkte und Schwellenwert)


Antworten:


150

Übergeben Sie eine Instanz einer anonymen Klasse als Ansichtsmodell? Ich habe es gerade versucht (dynamisches Ansichtsmodell in CSHTML) und habe den gleichen Fehler wie bei der Verwendung einer anonymen Klasse erhalten, aber es hat gut funktioniert, wenn ich eine benannte Klasse erstellt habe. Ich habe gesucht, aber nirgendwo dokumentiert.

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

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

EDIT # 1:

Laut David Ebbo können Sie einen anonymen Typ nicht an eine dynamisch typisierte Ansicht übergeben, da die anonymen Typen als kompiliert werden internal. Da die CSHTML-Ansicht in einer separaten Assembly kompiliert wird, kann sie nicht auf die Eigenschaften des anonymen Typs zugreifen.

EDIT # 2:

David Ebbo hat seinen Beitrag mit folgender Klarstellung bearbeitet:

Hinweis (22.12.2011): Da MVC 3 die Dynamik direkt unterstützt, ist die folgende Technik nicht mehr erforderlich. Dieser Beitrag hat tatsächlich dazu geführt, dass die Funktion in MVC integriert wurde!


1
Die Bearbeitung ist schön zu wissen. Ich hatte nur das gleiche Problem und verstand die WTF dort nicht. Danke für die Erklärung.
Yanick Rochon

18
EDIT # 2 schlägt vor, dass jetzt (MVC> 3) möglich ist, Zeile mit "Fehler" zu markieren? return View(new { Foo = 1, Bar = "test" });? Weil ich MVC 4 benutze und immer noch "Objekt enthält keine Definition für Foo" bekomme
Sport

@sports me too ... hast du eine Problemumgehung gefunden? (neben dem ToExpandoeinen)
Alex

2
Jetzt, im Jahr 2018 mit ASP.NET Core 2.1- und Razor-Ansichten, finde ich, dass der Fehler in der ursprünglichen Frage mich immer noch beißt. Ich weiß also nicht, worum es in diesem Vortrag über MVC 3 geht, da dies immer noch kaputt zu sein scheint.
Andrew Arnott

41

Unter .NET 4.0 können anonyme Typen problemlos in ExpandoObjects konvertiert werden, sodass alle Probleme mit dem Overhead der Konvertierung selbst behoben werden. Hier geht es raus


Bitte schön. Vielleicht tritt dies M $, um die anonymen Typen
benutzerfreundlicher

Gilt dies jedoch für Partials? Ich habe eine Fehlermeldung erhalten, dass Partials nicht dynamisch versendet werden können ...
John Bubriski

1
Welche Teiltöne? Können Sie ein Beispiel geben?
Adaptabi

27

Dies hat nichts mit anonymen Typen mit internen Eigenschaften zu tun

Es ist durchaus möglich , anonyme Typen von einer Ansicht an eine Teilansicht zu übergeben

Ich bin heute auf dasselbe Problem gestoßen, und es hatte nichts (direkt) mit dem Problem zu tun, anonyme Typen und ihre inhärenten internalEigenschaften zu übergeben.

In Bezug auf die OP-Frage ist die Antwort von @Lucas daher irrelevant - auch wenn die Problemumgehung funktioniert .

In der OP-Frage wird ein anonymer Typ von einer Ansicht in Baugruppe X an einen Teil in Baugruppe X übergeben . Daher ist das von David Ebbo skizzierte Problem, dass die Eigenschaften für anonyme Typen intern sind, ohne Bedeutung. Die für die Ansicht kompilierten Typen, der partielle und der anonyme Typ sind alle in derselben Assembly enthalten .

Was verursacht also das plötzliche Versagen, einen anonymen Typ von einer Ansicht an einen Teil zu übergeben?

Zumindest in meiner Situation stellte ich fest, dass es an einer anderen Ansicht im GLEICHEN ORDNER lag, die einen Modelltyp angibt, der nicht aufgelöst werden kann . Ansichten werden zur Laufzeit kompiliert, und daher wäre es sinnvoll, wenn ein Fehler zur Laufzeit beim Kompilieren der Ansichten auch einen Fehler beim Kompilieren der dynamischen Typen bedeuten würde und der Teil einfach eine erhalten würdeobject . Es ist nicht sofort klar, was los ist, aber im spezifischen Beispiel des OP (und meinem) ist dies höchstwahrscheinlich die Ursache des Problems.

Es ist interessant festzustellen, dass anonyme Typen nicht in gleicher Weise betroffen sind, wenn der Modelltyp korrekt ist, ein anderer Teil der Ansicht jedoch nicht kompiliert wird. Dies muss darauf zurückzuführen sein, wie Razor die dynamische Kompilierung der Bestandteile der Ansicht aufteilt.

Wenn Sie die fehlerhafte Ansicht korrigiert haben, erstellen Sie entweder die gesamte Lösung neu oder bereinigen und erstellen Sie das Projekt neu, bevor Sie überprüfen, ob es behoben ist.

Um sicherzustellen, dass Sie nicht erneut davon betroffen sind, können Sie die Kompilierungszeitkompilierung Ihrer Razor-Ansichten aktivieren, indem Sie dies Ihrer csprojDatei hinzufügen :

<PropertyGroup>
    <MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>

2
Dies hat mein Problem behoben - die Verwendung von "@model dynamic" schien zunächst die richtige Lösung zu sein, führte mich aber tatsächlich auf den falschen Weg.
Crimbo

Ich habe die Lösung gereinigt, neu aufgebaut und der Fehler ist verschwunden. 121 Stimmen sind falsch platziert.
Maxbeaudoin

Ich habe meine Antwort aktualisiert, um die Unterstützung von MVC für dynamische Ansichtsmodelle seit MVC 3 widerzuspiegeln.
Lucas

Das Aktivieren der Kompilierung von Ansichten von Zeit zu Zeit ist immer nützlich für eine große Codebasis. Enthüllt alle möglichen Probleme, Tippfehler, Fehler mit T4MVC dank der eingeführten starken Typisierung usw.
Denis The Menace

Oh, richtig: Ich habe gerade bemerkt, dass wir hier über den Übergang von einem Blick zu einem Teil sprechen. Nicht von einem Controller zu einer Ansicht, was mein Problem ist.
Mwardm

9

Fügen Sie die folgende Klasse an einer beliebigen Stelle in Ihrer Lösung hinzu (verwenden Sie den System-Namespace, damit Sie sie verwenden können, ohne Referenzen hinzufügen zu müssen) -

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

        }
    }

Wenn Sie das Modell an die Ansicht senden, konvertieren Sie es in Expando:

    return View(new {x=4, y=6}.ToExpando());

1
Es scheint mir ein unnötiger Aufwand zu sein, zuerst ein dynamisches Objekt und dann ein ExpandoObject zu erstellen ... Erstellen Sie stattdessen einfach das ExpandoObject.
Baz1nga

@ Baz1nga Du kannst nicht ... new Expando () {prop = value, ...}, was es problematisch macht. Ich verwende Json.Nets JObject für eine ähnliche Verwendung.
Tracker1

3
Es fühlt sich falsch an, HtmlHelper dort zu haben ... public static ExpandoObject ToExpando (dieses Objekt o) {IDictionary <Zeichenfolge, Objekt> expando = new ExpandoObject (); foreach (var propertyInfo in o.GetType (). GetProperties ()) {expando.Add (neues KeyValuePair <Zeichenfolge, Objekt> (propertyInfo.Name, propertyInfo.GetValue (o, Index: null)); } return (ExpandoObject) expando; }
erlando

6

Anstatt den dynamicModelltyp in der Teilansicht zu verwenden.

Sie können die anonymen Objektattribute mit @ViewData.Eval("foo")anstelle von aufrufen@Model.foo .

Dann können Sie @Model dynamicaus der Ansicht entfernen .

Ich bin kürzlich auf dieses Problem gestoßen, als ich einige Attribute zwischen Ansichten für die Integration von sozialen Kommentaren auf Facebook übergeben habe. Beispielcode:

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

Dann hatte ich aus meiner Sicht gerade diese Div:

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

0

Ich bin nicht sicher, ob Sie diesen Fehler erhalten, weil Sie die Problemumgehung nicht implementieren. Ich habe den gleichen Fehler in einer Teilansicht. Die Lösung bestand nur darin, den Build zu bereinigen und neu zu erstellen. Wenn die Syntax korrekt ist, sollte der Code funktionieren, aber die Razor Engine aktualisiert die Codeänderungen möglicherweise nicht richtig.


0

Ich habe dieses Problem mithilfe eines Wörterbuchs umgangen.

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

-6

Um dynamictype zu verwenden, müssen Sie auf Microsoft.CSharpAssembly verweisen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.