Ich möchte sagen, dass Sie den Begriff ViewModel für beide Richtungen der Client-Interaktion wiederverwenden. Wenn Sie genügend ASP.NET MVC-Code in der freien Wildbahn gelesen haben, haben Sie wahrscheinlich den Unterschied zwischen einem ViewModel und einem EditModel gesehen. Ich denke, das ist wichtig.
Ein ViewModel stellt alle Informationen dar, die zum Rendern einer Ansicht erforderlich sind. Dies kann Daten einschließen, die an statischen nicht interaktiven Orten gerendert werden, und auch Daten, die lediglich dazu dienen, eine Prüfung durchzuführen, um zu entscheiden, was genau gerendert werden soll. Eine Controller-GET-Aktion ist allgemein dafür verantwortlich, das ViewModel für seine Ansicht zu packen.
Ein EditModel (oder vielleicht ein ActionModel) stellt die Daten dar, die zum Ausführen der Aktion erforderlich sind, die der Benutzer für diesen POST ausführen wollte. Ein EditModel versucht also wirklich, eine Aktion zu beschreiben. Dies wird wahrscheinlich einige Daten aus dem ViewModel ausschließen und obwohl ich damit verwandt bin, ist es wichtig zu erkennen, dass sie tatsächlich anders sind.
Eine Idee
Das heißt Sie sehr leicht eine AutoMapper Konfiguration für das Gehen von Modell haben könnte -> Ansichtsmodell und eine andere von EditModel zu gehen -> Modell. Dann müssen die verschiedenen Controller-Aktionen nur AutoMapper verwenden. Hell könnte das EditModel eine Funktion haben, um seine Eigenschaften gegen das Modell zu validieren und diese Werte auf das Modell selbst anzuwenden. Es macht nichts anderes und Sie haben ModelBinders in MVC, um die Anfrage trotzdem dem EditModel zuzuordnen.
Eine weitere Idee
Jenseits dieses etwas, das ich diese Art von der Idee eines ActionModel abarbeitet etwa vor kurzem gedacht haben, ist, dass der Kunde, was zurück zu Ihnen Entsendung ist eigentlich die Beschreibung mehrerer Aktionen der Benutzer durchgeführt und nicht nur ein großer Datenklumpen. Dies würde sicherlich erfordern einige Javascript auf der Client-Seite zu verwalten, aber die Idee ist faszinierend, denke ich.
Im Wesentlichen, da der Benutzer Aktionen auf dem Bildschirm ausführt, den Sie ihnen präsentiert haben, würde Javascript eine Liste von Aktionsobjekten erstellen. Ein Beispiel ist möglicherweise, dass sich der Benutzer auf einem Mitarbeiterinformationsbildschirm befindet. Sie aktualisieren den Nachnamen und fügen eine neue Adresse hinzu, weil der Mitarbeiter gerade verheiratet war. Unter dem Deckmantel erzeugt dies eine ChangeEmployeeName
und eine AddEmployeeMailingAddress
Objekte zu einer Liste. Der Benutzer klickt auf "Speichern", um die Änderungen zu bestätigen, und Sie übermitteln die Liste mit zwei Objekten, von denen jedes nur die Informationen enthält, die für die Ausführung der einzelnen Aktionen erforderlich sind.
Sie würden einen intelligenteren ModelBinder benötigen, dann sollte der standardmäßige, aber gute JSON-Serializer in der Lage sein, die Zuordnung der clientseitigen Aktionsobjekte zu den serverseitigen zu übernehmen. Die serverseitigen (wenn Sie sich in einer 2-Tier-Umgebung befinden) könnten leicht Methoden haben, die die Aktion für das Modell, mit dem sie arbeiten, abgeschlossen haben. Die Controller-Aktion erhält also nur eine ID für die Model-Instanz und eine Liste mit Aktionen, die ausgeführt werden sollen. Oder die Aktionen haben die ID in sich, um sie sehr getrennt zu halten.
Also vielleicht so etwas wie dieses wird auf der Serverseite realisiert:
public interface IUserAction<TModel>
{
long ModelId { get; set; }
IEnumerable<string> Validate(TModel model);
void Complete(TModel model);
}
[Transaction] //just assuming some sort of 2-tier with transactions handled by filter
public ActionResult Save(IEnumerable<IUserAction<Employee>> actions)
{
var errors = new List<string>();
foreach(var action in actions)
{
// relying on ORM's identity map to prevent multiple database hits
var employee = _employeeRepository.Get(action.ModelId);
errors.AddRange(action.Validate(employee));
}
// handle error cases possibly rendering view with them
foreach(var action in editModel.UserActions)
{
var employee = _employeeRepository.Get(action.ModelId);
action.Complete(employee);
// against relying on ORMs ability to properly generate SQL and batch changes
_employeeRepository.Update(employee);
}
// render the success view
}
Das ist wirklich die Entsendung Aktion zurück macht ziemlich allgemein, da Sie auf Ihrer Modelbinder setzen Sie die richtige IUserAction Instanz und Ihre IUserAction Instanz zu erhalten entweder die richtige Logik selbst ausführen oder (wahrscheinlicher) mit der Information in das Modell aufrufen.
Wenn Sie sich in einer 3-Tier-Umgebung befanden, konnten mit der IUserAction einfach einfache DTOs erstellt werden, die über die Grenze hinweg aufgenommen und in einer ähnlichen Methode auf der App-Ebene ausgeführt wurden. Je nachdem, wie Sie diese Ebene erstellen, kann sie sehr einfach aufgeteilt werden und bleibt trotzdem in einer Transaktion (was Agathas Anfrage/Antwort und die Nutzung der Identitätskarte von DI und NHibernate betrifft).
Ich bin mir sicher, es ist keine perfekte Idee, es würde einige JS auf Client-Seite erfordern, zu verwalten, und ich war noch nicht in der Lage, ein Projekt zu tun, um zu sehen, wie es sich entfaltet, aber der Post versuchte es Denk darüber nach, wie du hin und zurück kommst, also dachte ich, ich würde meine Gedanken geben. Ich hoffe, es hilft und ich würde gerne von anderen Möglichkeiten hören, um die Interaktionen zu verwalten.
Ich bin nicht sicher AutoMapper nützlich ist hier, da es Abflachung nicht rückgängig machen kann. Domain Model ist schließlich kein einfaches DTO wie das View Model, daher reicht es unter Umständen nicht aus, ihm Eigenschaften zuzuweisen. Wahrscheinlich sollten einige Aktionen für das Domänenmodell gemäß den Inhalten von View Model durchgeführt werden. Allerdings +1 für die Freigabe ziemlich gut Ansatz. –
@Anton ValueInjecter kann flattening umkehren;) – Omu
Mit diesem Ansatz halten Sie den Controller nicht dünn, Sie verletzen SoC und DRY ... wie Omu erwähnt, sollten Sie eine separate Schicht haben, die sich um die Kartierung kümmern. – Rookian