Was sind die Best Practices für Asp.net MVC Seitenaufbau, um Parallelität und Effizienz zu ermöglichen?

8

Ich fand es schwierig, mit irgendetwas in dieser Kritik von ASP.net MVCs Framework für die Seitenzusammensetzung zu argumentieren.

Ссылка

Besonders diese Punkte:

  • Kein Zugriff auf View- oder Partial View-Instanzen
  • ViewData ist Ihr lose typisierter Informationsträger
  • Controller hat nicht wirklich die Kontrolle
  • Untergeordnete Aktionen haben keinen Sinn für den Anfragekontext
  • Ansichten sind mit Controllern verbunden

Für kleine Anwendungen glaube ich nicht, dass viele davon ein großes Problem darstellen, aber in großen Anwendungen, in denen Sie viele gemeinsam genutzte Komponenten wiederverwenden möchten, oder selbst wenn Sie nur eine große Anwendung haben Abhängig von mehreren Back-End-Informationsquellen, um alle Informationen zu erhalten, die zum Rendern einer Ansicht erforderlich sind, beginnt sie zu stürzen.

Es wurden verschiedene Halblösungen für diese Probleme vorgeschlagen, die jedoch nicht gut skalierbar sind oder unerwünschte Design-Einschränkungen aufweisen.

Hier ist ein Anwendungsbeispiel:

  1. 50% des Seiteninhalts sind auf allen Seiten innerhalb einer Anwendung üblich (Kopfzeile, Fußzeile, Menüs usw.)
  2. Ihre Anwendung besteht möglicherweise aus mehreren Bereichen mit jeweils eigenen Controllern usw. für die unabhängige Entwicklung.
  3. Eine Anzahl der Seitenelemente (Menüs, Seitenkopfinformationen, Fußzeilen, Offenlegungen), die sich im allgemeinen Seiteninhalt befinden, erfordern einen oder mehrere Serviceaufrufe, um die Daten zum Rendern auszufüllen.

Okay, also sagen Sie in asp.net mvc3, dass Sie ein gemeinsames Razor-Layout teilen möchten, das die 50% allgemeine Benutzeroberfläche enthält. Dies hilft bei der Trennung von Bedenken in dieser Anwendung Entwickler müssen nicht besorgt sein über gemeinsame ui und können sich auf die Logik und Ansichten für ihre Fachkompetenz konzentrieren.

Dies bricht jedoch vollständig zusammen, wenn dieses geteilte Layout Daten benötigt (etwas Anschein von einem oder mehreren Modelltypen), um sich vollständig zu rendern. Sie haben möglicherweise unabhängige Elemente auf der Seite, die jeweils ein bestimmtes Datenmodell benötigen, z. * primäres Menü-Modell * sekundäres Menü-Modell * Fußzeile verbindet Modell * Berechtigungsmodell * footer Disclaimer Modell

Und jedes dieser Modelle kann separate Quellen haben. Obwohl Sie die Vorlage teilen können, gibt es keine einfache Möglichkeit, die Logik für die Erstellung dieser Modelle zu teilen - und es gibt definitiv keine, die generisch, erweiterbar und performant ist, die ich gesehen habe.

Einige Ansätze für dieses Problem, die ich gesehen habe, sind:

  • Geben Sie das allgemeine Layout stark ein , was erfordert, dass alle Ansichtsmodelle eine gemeinsame Basismodellklasse unterklassifizieren. (Es gibt jedoch keine allgemeine Lösung, ein solches Metamodell zu bevölkern, und dies ist im Design einschränkend und macht Modelle riesig und schwieriger zu testen.) Darüber hinaus fällt die Modellpopulation immer noch an jeden Controller und verletzt die Trennung von Bedenken und das Prinzip der einfachen Verantwortlichkeit die Unit-Testing-Controller zu komplizieren, indem eine Menge zusätzlicher Logik angehäuft wird, um das Metamodell zusätzlich zu den sichtspezifischen Modellinformationen zu füllen.
  • Lassen Sie das allgemeine Layout nicht typisiert , damit Sie nicht von einem allgemeinen Basismodell erben müssen. Dazu müssen Sie ViewData oder ViewBag verwenden, um alle unterschiedlichen Modelle zu kommunizieren, die die Vorlage benötigt, damit Sie verlieren starke Tippvorteile und enden mit einem losen Datenvertrag. Sie haben immer noch das Problem, dass es keine allgemeine Lösung zum Auffüllen des Metamodells und allem, was damit einhergeht, gibt.
  • Jeder Controller muss eine gemeinsame Basis-Controller-Klasse ableiten, um ein gemeinsames Layout und Modell zu unterstützen. Die Logik zum Aufbau der gemeinsamen Aspekte des Meta-Modells geht hier. Dies ist jedoch nicht immer eine wünschenswerte Architektur- oder Entwurfsbeschränkung. Dies löst zumindest die Problemtrennung.
  • Anstelle eines Metamodells verwenden unter Verwendung von RenderAction () in Ihrem allgemeinen Layout untergeordnete Aktionen , um wieder verwendbare Portlet-Widgets zu erstellen, die unabhängig voneinander wissen, wie sie ihr Datenmodell erstellen und bereitstellen ihre Sichtweise. Dies ist wirklich gut für die Trennung von Bedenken, hat aber seine eigene Litanei von Schattenseiten: Ansichten, die während des Renderings über die Kindaktionen effektiv Dienstaufrufe machen, Kindaktionen sind sich des ursprünglichen Anfragekontextes völlig nicht bewusst, verletzen das DRY-Prinzip, wie es jeder Kindaktion nicht weiß was vorher gegangen ist, damit jeder die gleichen Serviceanrufe immer wieder in der gleichen HTTP-Anfrage stellen kann, und andere. Stellen Sie sich 20-30 Elemente einer Seite vor, die alle unabhängig von RenderAction () aufgerufen werden müssen ...

Es gibt weitere Fälle (einige sind auch im Stackoverflow zu sehen), wo es Probleme mit RenderAction () als Lösung gibt. z.B. Die Tatsache, dass mehrere RenderAction () -Aufrufe in einer Schleife ausgegeben werden, führt zu einer seriellen Ausführung aller dieser Controller-Methoden.Mit RenderAction () besteht keine Möglichkeit zur Parallelität. E / A-gebundene Serviceaufrufe in jeder untergeordneten Controller-Aktion bewirken, dass der gesamte Renderprozess auf E / A wartet. Ein Controller hat nur Kenntnisse über seine unmittelbare Ansicht und sein Modell und nichts hat ein vollständiges Bild dessen, was in der Ansicht sein wird, um einige Operationen zu parallelisieren.

Der Autor der obigen Kritik hat ein anderes UI-Modell auf ASP.Net mvc namens Quartz entwickelt, das es einem God Controller ermöglicht, die Ansichten genau zu kennen und jedem von ihnen ein View-Modell zu übergeben, damit es parallelisiert werden kann Der Service ruft an einem zentralen Ort auf, um diese Ansichtsmodelle zu erstellen. Ich weiß nicht, ob dies das beste Design ist, um die Probleme zu lösen, aber es sieht vielversprechend aus.

Meine Frage ist, was ist die beste Vorgehensweise beim Erstellen einer komplexen Anwendung auf ASP.Net MVC, die diese Probleme sauber löst? Ich habe über ein paar Möglichkeiten nachgedacht (obwohl keine in ASP.Net MVC praktisch sein kann - das ist TBD), aber jemand anderes muss schon hier hineingelaufen sein. Was sind die Entwurfsmuster in ASP.Net MVC oder was kommt auf den Hecht, der dies zu einem handhabbaren Problem machen könnte?

    
core24 21.12.2011, 23:37
quelle

2 Antworten

2

Ich persönlich denke, dass die Vorteile der Verwendung von Child Actions per RenderAction die Nachteile überwiegen.

Sie können Elemente vom Typ "Widget" erstellen und ihre Logik in eine Controller-Aktion einschließen. Auf diese Weise kann die Ansicht, die das Widget aufruft, ziemlich unwissend darüber bleiben, was die untergeordnete Aktion tut und wie sie es tut eine nette Trennung der Sorgen.

Sie haben die Nachteile dieses Ansatzes beschrieben, aber ich denke, dass die negativen Auswirkungen mit einer vernünftigen Caching-Strategie minimiert werden können.

    
StanK 22.12.2011 00:11
quelle
1

Ich bin mir nicht sicher, ob ich wirklich viel mehr zu dieser "Frage" beitragen kann. Ich denke, Sie haben ein gutes Verständnis für die Probleme und Lösungen, Vor- und Nachteile.

In der App, an der ich gerade arbeite, verwenden wir einige dieser Ansätze, indem wir sowohl ein Basismodell-Objekt als auch einen Basis-Controller haben. Um Roundtrips zu minimieren, speichern wir einige Daten in der Sitzung und füllen sie erneut im Modell auf, indem Sie OnActionExecuted im Basis-Controller überschreiben und das Modell aus dem Kontext herausnehmen und Eigenschaften außerhalb der Sitzung festlegen.

Ich würde sicherlich auch gerne wunderbare Lösungen hören, aber ich denke, dies sind nur die Kompromisse, die es zu bewältigen gilt.

    
Matt Klinker 21.12.2011 23:57
quelle