Aus dieser Frage geht hervor , dass es sinnvoll ist, einen Controller ein ViewModel erstellen zu lassen , das das Modell, das in der Ansicht angezeigt werden soll, genauer wiedergibt. Ich bin jedoch neugierig auf einige der Konventionen (ich bin neu im MVC-Muster) , wenn es nicht schon offensichtlich war).
Grundsätzlich hatte ich folgende Fragen:
- Normalerweise möchte ich eine Klasse / Datei haben. Ist dies bei einem ViewModel sinnvoll, wenn es nur erstellt wird, um Daten von einem Controller an eine Ansicht zu übergeben?
- Wenn ein ViewModel in eine eigene Datei gehört und Sie eine Verzeichnis- / Projektstruktur verwenden, um die Dinge getrennt zu halten, wohin gehört die ViewModel- Datei? Im Controller- Verzeichnis?
Das ist es im Grunde für jetzt. Ich habe vielleicht noch ein paar Fragen, aber das hat mich in der letzten Stunde oder so gestört, und ich kann anscheinend anderswo konsequente Anleitungen finden.
BEARBEITEN: Wenn ich mir die Beispiel- NerdDinner-App auf CodePlex ansehe , sieht es so aus, als ob die ViewModels Teil der Controller sind , aber es ist mir trotzdem unangenehm, dass sie nicht in ihren eigenen Dateien enthalten sind.
quelle
Antworten:
Ich erstelle für jede Ansicht ein sogenanntes "ViewModel". Ich habe sie in einem Ordner namens ViewModels in meinem MVC-Webprojekt abgelegt. Ich benenne sie nach dem Controller und der Aktion (oder Ansicht), die sie darstellen. Wenn ich also Daten an die SignUp-Ansicht auf dem Membership Controller übergeben muss, erstelle ich eine MembershipSignUpViewModel.cs-Klasse und lege sie in den ViewModels-Ordner.
Dann füge ich die notwendigen Eigenschaften und Methoden hinzu, um die Übertragung von Daten vom Controller zur Ansicht zu erleichtern. Ich verwende den Automapper, um von meinem ViewModel zum Domänenmodell und bei Bedarf wieder zurück zu gelangen.
Dies funktioniert auch gut für zusammengesetzte ViewModels, die Eigenschaften enthalten, die vom Typ anderer ViewModels sind. Wenn Sie beispielsweise 5 Widgets auf der Indexseite im Mitgliedschafts-Controller haben und für jede Teilansicht ein ViewModel erstellt haben, wie übergeben Sie die Daten aus der Index-Aktion an die Partials? Sie fügen dem MembershipIndexViewModel eine Eigenschaft vom Typ MyPartialViewModel hinzu, und beim Rendern des Teils würden Sie Model.MyPartialViewModel übergeben.
Auf diese Weise können Sie die partiellen ViewModel-Eigenschaften anpassen, ohne die Indexansicht ändern zu müssen. Es wird immer noch nur in Model.MyPartialViewModel übergeben, sodass die Wahrscheinlichkeit geringer ist, dass Sie die gesamte Kette von Partials durchlaufen müssen, um etwas zu reparieren, wenn Sie dem partiellen ViewModel lediglich eine Eigenschaft hinzufügen.
Ich werde auch den Namespace "MyProject.Web.ViewModels" zur web.config hinzufügen, damit ich sie in jeder Ansicht referenzieren kann, ohne jemals eine explizite Importanweisung für jede Ansicht hinzuzufügen. Macht es nur ein bisschen sauberer.
quelle
Das Trennen von Klassen nach Kategorien (Controller, ViewModels, Filter usw.) ist Unsinn.
Wenn Sie Code für den Home-Bereich Ihrer Website (/) schreiben möchten, erstellen Sie einen Ordner mit dem Namen Home und legen Sie dort den HomeController, IndexViewModel, AboutViewModel usw. und alle zugehörigen Klassen ab, die von Home-Aktionen verwendet werden.
Wenn Sie gemeinsam genutzte Klassen wie einen ApplicationController haben, können Sie diese im Stammverzeichnis Ihres Projekts ablegen.
Warum verwandte Dinge trennen (HomeController, IndexViewModel) und Dinge zusammenhalten, die überhaupt keine Beziehung haben (HomeController, AccountController)?
Ich habe einen Blog-Beitrag zu diesem Thema geschrieben.
quelle
Ich behalte meine Anwendungsklassen in einem Unterordner namens "Core" (oder einer separaten Klassenbibliothek) und verwende dieselben Methoden wie die KIGG- Beispielanwendung, jedoch mit einigen geringfügigen Änderungen, um meine Anwendungen trockener zu machen.
Ich erstelle eine BaseViewData-Klasse in / Core / ViewData /, in der ich allgemeine standortweite Eigenschaften speichere.
Danach erstelle ich alle meine ViewData-Klassen in demselben Ordner, die dann von BaseViewData abgeleitet sind und ansichtsspezifische Eigenschaften haben.
Dann erstelle ich einen ApplicationController, von dem alle meine Controller abgeleitet sind. Der ApplicationController verfügt über eine generische GetViewData-Methode wie folgt:
Schließlich mache ich in meiner Controller-Aktion Folgendes, um mein ViewData-Modell zu erstellen
Ich denke, das funktioniert wirklich gut und hält Ihre Ansichten aufgeräumt und Ihre Controller dünn.
quelle
Eine ViewModel-Klasse dient dazu, mehrere durch Instanzen von Klassen dargestellte Daten in ein einfach zu verwaltendes Objekt zu kapseln, das Sie an Ihre Ansicht übergeben können.
Es wäre sinnvoll, Ihre ViewModel-Klassen in ihren eigenen Dateien im eigenen Verzeichnis zu haben. In meinen Projekten habe ich einen Unterordner des Ordners Models namens ViewModels. Dort leben meine ViewModels (zB
ProductViewModel.cs
).quelle
Es gibt keinen guten Ort, an dem Sie Ihre Modelle aufbewahren können. Sie können sie in einer separaten Baugruppe aufbewahren, wenn das Projekt groß ist und viele ViewModels (Datenübertragungsobjekte) vorhanden sind. Sie können sie auch in einem separaten Ordner des Site-Projekts aufbewahren. In Oxite werden sie beispielsweise in einem Oxite-Projekt platziert, das auch viele verschiedene Klassen enthält. Controller in Oxite werden in ein separates Projekt verschoben, und Ansichten befinden sich ebenfalls in einem separaten Projekt.
In CodeCampServer heißen ViewModels * Form und werden im UI-Projekt im Ordner Models abgelegt.
Im MvcPress- Projekt werden sie im Datenprojekt platziert, das auch den gesamten Code für die Arbeit mit der Datenbank und ein bisschen mehr enthält (aber ich habe diesen Ansatz nicht empfohlen, er dient nur als Beispiel).
Sie sehen also, dass es viele Gesichtspunkte gibt. Normalerweise behalte ich meine ViewModels (DTO-Objekte) im Site-Projekt. Aber wenn ich mehr als 10 Modelle habe, ziehe ich es vor, sie in eine separate Baugruppe zu verschieben. Normalerweise verschiebe ich in diesem Fall auch die Steuerungen, um die Baugruppe zu trennen.
Eine andere Frage ist, wie Sie alle Daten vom Modell einfach Ihrem ViewModel zuordnen können. Ich schlage vor, einen Blick auf die AutoMapper- Bibliothek zu werfen . Ich mag es sehr, es erledigt alles Drecksarbeit für mich.
Außerdem schlage ich vor, das SharpArchitecture- Projekt zu betrachten. Es bietet eine sehr gute Architektur für Projekte und enthält viele coole Frameworks und Anleitungen sowie eine großartige Community.
quelle
Hier ist ein Code-Ausschnitt aus meinen Best Practices:
quelle
Wir werfen alle unsere ViewModels in den Ordner Models (unsere gesamte Geschäftslogik befindet sich in einem separaten ServiceLayer-Projekt).
quelle
Persönlich würde ich vorschlagen, wenn das ViewModel alles andere als trivial ist, dann verwenden Sie eine separate Klasse.
Wenn Sie mehr als ein Ansichtsmodell haben, ist es sinnvoll, es in mindestens ein Verzeichnis zu partitionieren. Wenn das Ansichtsmodell später freigegeben wird, erleichtert der im Verzeichnis enthaltene Namensraum das Verschieben in eine neue Assembly.
quelle
In unserem Fall haben wir die Modelle zusammen mit den Controllern in einem Projekt, das von den Ansichten getrennt ist.
Als Faustregel haben wir versucht, die meisten ["..."] ViewData-Inhalte in das ViewModel zu verschieben und zu vermeiden. Daher vermeiden wir Castings und magische Zeichenfolgen, was eine gute Sache ist.
Das ViewModel enthält auch einige allgemeine Eigenschaften wie Paginierungsinformationen für Listen oder Kopfzeileninformationen der Seite zum Zeichnen von Breadcrumbs und Titeln. In diesem Moment enthält die Basisklasse meiner Meinung nach zu viele Informationen, und wir können sie in drei Teile teilen, die grundlegendsten und notwendigsten Informationen für 99% der Seiten eines Basisansichtsmodells und dann ein Modell für die Listen und ein Modell für die Formulare, die bestimmte Daten für diese Szenarien enthalten und von der Basis erben.
Schließlich implementieren wir für jede Entität ein Ansichtsmodell, um mit den spezifischen Informationen umzugehen.
quelle
Code in der Steuerung:
Code im Ansichtsmodell:
Projekte:
DevJet.Web (das ASP.NET MVC-Webprojekt)
DevJet.Web.App.Dictionary (ein separates Klassenbibliotheksprojekt)
In diesem Projekt habe ich einige Ordner erstellt wie: DAL, BLL, BO, VM (Ordner für Ansichtsmodelle)
quelle
Erstellen Sie eine Basisklasse für das Ansichtsmodell, für die häufig erforderliche Eigenschaften wie das Ergebnis der Operation und Kontextdaten erforderlich sind. Sie können auch aktuelle Benutzerdaten und Rollen einfügen
In der Basis-Controller-Klasse haben Sie eine Methode wie PopulateViewModelBase (). Diese Methode füllt die Kontextdaten und Benutzerrollen. Mit HasError und ErrorMessage werden diese Eigenschaften festgelegt, wenn beim Abrufen von Daten aus service / db eine Ausnahme auftritt. Binden Sie diese Eigenschaften in der Ansicht, um Fehler anzuzeigen. Benutzerrollen können verwendet werden, um den ausgeblendeten Abschnitt in der Ansicht basierend auf Rollen anzuzeigen.
Um Ansichtsmodelle in verschiedenen Abrufaktionen zu füllen, kann sie konsistent gemacht werden, indem der Basiscontroller mit der abstrakten Methode FillModel verwendet wird
In Steuerungen
quelle