Umgang mit komplexen Ansichten (bestehend aus mehreren Teilen) in einer MVC-Webanwendung

7

Nehmen wir an, ich schreibe eine Blog-Webanwendung mit MVC-Muster. Ein typisches Layout für die Hauptseite der Blog-Anwendung ist - eine Art Post-Index im Hauptteil. Abgesehen davon gibt es einige zusätzliche Teile wie die Zeitleiste, das Tag-Navigationsfeld, das Abonnement-Feld usw. Diese Steuerelemente werden auch in einem einzelnen angezeigt Post-Ansicht und kann in anderen Ansichten erscheinen, die ich habe.

Meine Frage ist - wie soll ich mit diesen Panels in meinen Ansichten und Controllern umgehen? Ich sehe hier drei Ansätze:

  1. Erstellen Sie eine große Ansichtsmodellklasse, die alle Informationen enthält, die zum Rendern der Ansichten erforderlich sind (entweder Index oder einzelner Beitrag). In diesem Fall könnte ich diese Seitenbereiche zu Teilansichten machen und sie aus der Ansicht aufrufen, die über einen Teil dieses großen Ansichtsmodells gerendert wird. Der Nachteil ist - ich werde das Code-Füll-Ansichtsmodell auf verschiedene Controller-Methoden verteilen, was bedeutet, dass der Code dupliziert wird. Welches ist ziemlich schlecht.

  2. Erstellen Sie eine weitere Ebene für das Rendern von Ansichten. Angenommen, die oberste Ebene des Renderns empfängt bereits gerenderte Teile von HTML oder Funktionen, die beim Aufruf ein HTML ausgeben. Die Ebene unter dieser "Teilebene kombinieren" würde nur Teilansichten für jedes gewünschte Bedienfeld ergeben, einschließlich Hauptinhalt. Der Nachteil hier - Speichernutzung. Die meisten modernen Frameworks rendern htmls direkt in den Ausgabestream, aber bei diesem Ansatz werden Teilansichten zuerst in Zeichenfolgenobjekte gerendert - was zu Speicheraufwand führt.

  3. Verwenden Sie so etwas wie "RenderAction" von asp.net mvc, das eine Controller-Methode aus einer Ansicht aufruft. Ich denke, dies ist eine schlechteste Lösung von 3 gegeben, weil es einen MVC-Ansatz fallen lässt.

Die Frage ist nicht an einen bestimmten Rahmen gebunden, ich möchte die allgemeine Vorgehensweise verstehen.

AKTUALISIEREN

Nach einer Antwort habe ich herausgefunden, dass der Beitrag nicht klar ist. Also vernünftiges Update hier:

Unter dem Begriff viewmodel verstehe ich ein Objekt, das alle Daten enthält, die zum Rendern einer bestimmten Ansicht erforderlich sind.

Bei allen drei Ansätzen werden Teilansichten mit einem eigenen Ansichtsmodell erstellt. Zum Beispiel (mit C # -Syntax):

class SinglePostViewModel {
  string Text {get;set;}
  string Title {get;set;}
  string Slug {get;set;}
  DateTime PublishedDate {get;set;}
  ...
}

class TagNavigationPanelViewModel {
  string TagText {get;set;}
  int PostsCount {get;set;}
}

class CalendarNavigationPanelViewModel {
  DateTime YearAndMonth {get;set;}
  int PostsCount {get;set;} 
}

Meine Frage ist - wie man diese Teilansichten gut miteinander kombiniert.

Hedin
quelle

Antworten:

1

Ich sehe eine andere Methode, die, sofern ich Ihren Beitrag nicht missverstanden habe, nicht erwähnt wurde:

Die Hauptansicht posthätte ihr Modell. Dieses Modell würde bestehen aus nur die Eigenschaften notwendig , diesen Beitrag anzuzeigen ( author, title, body, usw.). Dann jedes Stück der postkann Ansicht , dass Sie denken ( timeline, tag navigation panel, subscribing panel, usw.), würde aufgeteilt in ihre eigenen Ansichten und jeder würde sein eigenes Modell haben. Auf diese Weise können Sie diese Modelle bei Bedarf in Ihrem Controller aufbauen.

Es mag unnötig klingen, diese auf diese Weise aufzuteilen, aber es eignet sich für das Prinzip der Einzelverantwortung . Konzentrieren Sie jede "Ansicht / jedes Modell" auf sich selbst, damit sie überall dort wiederverwendet werden kann, wo sie benötigt wird.

Wenn Sie das Gefühl haben, dass sich Ihr Code allmählich selbst dupliziert, was abhängig von Ihrer Situation sein kann, sollten Sie eine Art "Hilfsklasse" schreiben. Diese Hilfsklasse würde den gesamten Modellaufbau an einem Ort abwickeln, und der gesamte andere doppelte Code würde auf einen Hilfsklassenaufruf reduziert.

ethorn10
quelle
Dies ist ein allgemeiner Ansatz, dem ich zu folgen versuche. Meine Frage war, wie man diese Teilansichten mit eigenen Modellen kombiniert. Trotzdem würde ich die Frage aktualisieren, um es klarer zu machen.
Hedin
1
Ich verstehe ... Entschuldigung für die anfängliche Verwirrung. Ich würde mich für die Containeransicht entscheiden, die persönlich alle erforderlichen Teilansichten enthält.
Ethorn10
1

Was ich mache, ist eine Variation / Kombination Ihrer Punkte 1 und 3. Ich kombiniere die Ansichtsmodelle in einer Containerklasse und verwende diese als "Haupt" -Ansichtsmodell. Die übergeben die Teile als Modelle an die Teiltöne.

Nach Ihrem Beispiel würde ich dieses Ansichtsmodell für die Standardseite erstellen:

class DefaultViewModel {
  public List<SinglePostViewModel> Posts ...
  public TagNavigationPanelViewModel Tags ...
  public CalendarNavigationPanelViewModel Calendar ...
  ...
}

In Default.cshtml

@model DefaultViewModel
...html for rendering the default page...


@Html.Partial("_TagNavigationPanel", Model.Tags)
...etc...

In _TagNavigationPanel.cshtml

@model TagNavigationPanelViewModel
...html+razor for rendering the tags...

Gehen Sie dann für eine einzelne Beitragsseite genauso vor:

class SinglePostPageViewModel {
  public SinglePostViewModel Post ...
  // no tags in single view, for example..
  // public TagNavigationPanelViewModel Tags ...
  public CalendarNavigationPanelViewModel Calendar ...
  // But a list of related, perhaps?
  public List<RelatedPosts> RelatedPosts
  ...
}

Und erstellen Sie Ihre Ansichten (cshtml (s)) entsprechend

Lorenzo Dematté
quelle
Darum geht es bei einem Ansatz. Bei 3rd geht es nur um den Aufruf von RenderAction oder @ Html.Action, bei dem die Controller-Methode aufgerufen wird. Danke für die Antwort!
Hedin
1
@ Hedin oh, ok ... Ich dachte, dass Ihr Ansatz Nr. 1 "monolithischer" war, mit einem großen (anderen) Ansichtsmodell. Also ja, ich benutze 1 und finde es gut. Ich mag auch das dritte weniger, aber es ist gut für das Caching. Wenn Sie Leistungsprobleme haben oder Teile der Ansicht zwischenspeichern müssen, kann es sich lohnen, es zu versuchen.
Lorenzo Dematté
Was ist mit dem Überspringen einer Teilansicht? zB basierend auf einer Benutzerrolle?
LifeH2O
0

- Sie können mit allen drei Subviews eine einzelne „Behälter“ Ansicht erstellen SinglePostView, TagNavigationPanelViewund CalendarNavigationPanelView. Sie können die SinglePostViewAnsicht auch durch eine andere Ansicht ersetzen, die für eine Seite erforderlich ist. Auf diese Weise müssen Sie nur die "zentrale" (Beitrags-) Ansicht für verschiedene Seiten durch einen anderen Ansichtstyp (z. B. Liste der Beiträge) ersetzen, und die anderen Ansichten müssen nur mit den entsprechenden Daten aktualisiert und nicht ersetzt werden.

Ihre Containeransicht (zum Beispiel MyView) sollte Verweise auf alle Unteransichten enthalten. Es kann verschiedene updateMethoden geben, mit denen verschiedene Unteransichten aktualisiert werden. Zum Beispiel - updateCalendar(CalendarNavigationPanelViewModel calendarData)oder updatePost(SinglePostViewModel postData). Oder sogar eine einzelne update(IViewModel modelData)- dann müssen Sie den Typ der (und die Besetzung) überprüfen, um modelDatazu bestimmen, welche Ansicht aktualisiert werden soll

stan0
quelle