Ich habe sowohl SO als auch Google durchsucht, aber keine relevante / akzeptable Antwort gefunden.
Hintergrund:
* Mit MVC 4.5
* Ich habe einige Generic Repo<T>
, die ich über EF5 verwende, auf die wiederum generische Service<T>
zugreifen
* Ich habe Domänenmodelle und Ansichtsmodelle und ich benutze Automapper, um zwischen ihnen zu mappen, geschieht diese Zuordnung in der Service
Schicht
* Darüber hinaus habe ich meine Controllers
, die wiederum so generisch wie möglich sind.
Also, zu der Frage; Ich habe ein paar Szenarien, wo ich dem Benutzer eine Liste von Optionen präsentieren muss und sie müssen eine oder mehrere auswählen. Die Optionen sind benutzerspezifisch, so dass meine Domäne User
eine List<Location>
hat, die ihre gespeicherten Speicherorte ist, und wenn sie Item
hinzufügen / ändern, müssen sie mindestens ein Location
auswählen.
< br>
Ich widerstehe der Versuchung, dieses List<Location>
in meinen Controllern zu holen, weil ich sie allgemein und schlank halten möchte, aber gleichzeitig möchte ich lieber nicht zwei Eigenschaften in meinem ItemView
-Modell haben, eines für AvailableLocations
und eines für SelectedLocations
, weil dieses Modell nicht nur zum Hinzufügen / Ändern, sondern auch für Suchergebnisse usw. verwendet wird.
Optionen:
* Sollte ich ein anderes Modell zum Hinzufügen / Ändern einer Item
, z. ItemInput
?
* Soll ich ein benutzerdefiniertes Mapping verwenden und Automapper holen, um die Liste der verfügbaren Orte zu erhalten?
* In welcher Schicht soll ich diese verfügbaren Standorte holen?
Was sind die Vorschläge der Leute zu einem sauberen und generischen Ansatz dazu?
Vielen Dank!
Ich würde so etwas tun:
%Vor%Dann in Ihrem Controller (ich folgte diesem von MVC Scaffolding):
%Vor%(oder Ihre eigene Checkbox-Liste) und setzen Sie ein Listing-Steuerelement auf der HTML / View-Seite.
Der Grund, warum ich glaube, dass dies die beste Methode ist, liegt darin, dass die Logik alle innerhalb des Dienstes liegt. Wenn Sie es in Ihr DTO / Datenmodell einfügen, können Sie auf dieses Problem stoßen:
Was passiert, wenn Sie zusätzliche Logik benötigen, um Standorte zurückzuziehen? d.h. Unterorte von Orten.
Sie ändern Ihren Dienst (oder die Überschreibung), um die neuen Änderungen widerzuspiegeln, und diese Logik würde in den Dienst eingefügt:
%Vor%ps. Ich verwende nie generische Dienste, der Grund, warum ich einen Dienst habe, ist, weil ein Teil des Datenzugriffs, den er bereitstellt, Logik enthält, die nicht mit dem generischen DAL zusammenpassen soll.
Ich könnte eine Schnittstelle oder einen abstrakten Dienst machen, um mein Leben ein wenig einfacher für allgemeine Operationen zwischen Diensten zu machen, aber wenn Sie sagen, ein konkretes, ein UserManagementSerive
sicher sagen Sie, dass Sie ein Objekt verwalten wollen, das Benutzer und hat Standorte und Objekte mit jeweils eigenen Funktionen?
Ich glaube nicht, dass es nur eine mögliche Antwort auf diese Frage gibt.
Ich würde einen einfachen, aber nicht so generischen Ansatz empfehlen. Ich würde schreiben, was ViewModels heißt, d. H. Modellklassen, die sich auf Ihre spezifischen Ansichten beziehen. Dann würde ich Ihre verfügbaren Speicherorte vom Controller abrufen und eine Instanz des ViewModel in Ihrem Controller mit den abgerufenen Speicherorten auffüllen.
Grundsätzlich würde ich einige Dienste wie:
verfügbar machen %Vor% Beachten Sie, dass ich IEnumerable<T>
, nicht IQueryable<T>
verwendet habe. Da die Implementierung die Datenbank tatsächlich anfordert, da sie zu fehleranfällig ist (zumindest IMO), wenn es die Rolle des Controllers ist, dies zu tun (erinnern Sie sich an die verzögerte Ausführung von IQueryable<T>
).
Und es gibt eine Domäneninstanz zurück, d. H. Eine Entität, kein zugeordnetes Modell. Ich würde mit nichts außer Domain-Klassen in der Service-Schicht persönlich umgehen. Es könnte Domänenklassen geben, die nicht Entitäten sind, aber z. B. Kompositionen von Entitäten. Dies könnte dazu beitragen, effiziente Anfragen zu erstellen und die Verwendung von Lazy-Loading und Deferred Execution in den Controllern zu vermeiden. Dies ist hilfreich, wenn der Controller ein ganzes Objektdiagramm und nicht nur eine Entität benötigt.
Dann würde ich Modelle und ViewModels wie folgt in der Web Application Assembly schreiben:
%Vor%ItemModel
und LocationModel
), die sich auf die Webanwendung beziehen. Dies bedeutet, dass es in diesen Modellen einige webbezogene Dinge geben könnte, z. B. berechnete schreibgeschützte Eigenschaften oder Attribute für Eigenschaften ( DisplayAttribute
... usw.).
Ich würde diese Modelle tatsächlich mehrere Male schreiben, weil ich nicht glaube, dass dies etwas ist, das verallgemeinert werden könnte: Zum Beispiel könnte eine Ansicht die Verwendung einer Navigationseigenschaft erfordern, während eine andere Ansicht dies nicht tun würde. Dies ändert die Tiefe des Zuordnungsprozesses in Abhängigkeit von den Ansichten, die das Modell verwenden. Und ich würde AutoMapper überhaupt nicht benutzen (nur handgeschriebene Mapper). CreateItemViewModel
), bei denen es sich um Objekte handelt, die mit einer einzelnen Ansicht verknüpft sind (z. B. die Ansicht, die das Erstellen eines Elements in diesem Beispiel ermöglicht). . Der Unterschied zwischen Model und ViewModel besteht darin, dass das ViewModel mit einer einzelnen Ansicht verknüpft ist (und entsprechend dieser Ansicht benannt wird). Auf der anderen Seite beziehen sich Modelle auf mehrere Ansichten (der Namespace würde helfen, die Ansichten zu kennen. Zum Beispiel xxx.Item.Models
für Modelle, die sich auf alle Ansichten im Verzeichnis xxx.Item
beziehen). ViewModels werden basierend auf den Domänenklassen neu im Controller (oder in einem separaten Mapper) erstellt. Im obigen Beispiel könnten Sie Domänenklassen erstellen, die AssociatedLocations
und AvailableLocations
zurückgeben, aber Ihre Serviceschicht muss sich des Webparts bewusst sein (ich meine, Ihre Serviceschnittstelle und Domänenklassen würden wissen, welche Eigenschaften für eine bestimmte Ansicht benötigt werden). Ich bin mir nicht sicher, ob diese Eigenschaften tatsächlich zu einer einzelnen Ansicht in Ihrer Anwendung gehören, aber wenn dies nicht der Fall ist, könnten Sie auch eine Domänenklasse als Zusammensetzung von Entitäten erstellen, die AssociatedLocations
und AvailableLocations
zurückgeben:
Tags und Links asp.net-mvc c# asp.net-mvc-4