Je tiens à dire que vous réutilisez le terme ViewModel pour les deux directions de l'interaction avec le client. Si vous avez lu assez ASP.NET MVC code dans la nature, vous avez probablement vu la distinction entre un ViewModel et un EditModel. Je pense que c'est important.
Un ViewModel représente toutes les informations nécessaires pour effectuer le rendu d'une vue. Cela pourrait inclure des données qui est rendu en statique non-interactive des lieux et également des données purement d'effectuer un contrôle de décider sur ce qu'est exactement le rendu. Un Contrôleur d'OBTENIR une action est généralement responsable de l'emballage jusqu'au ViewModel pour son point de Vue.
Un EditModel (ou peut-être un ActionModel) représente les données requises pour exécuter l'action de l'utilisateur voulais faire pour ce POST. Donc un EditModel est vraiment essayer de décrire une action. Ce sera probablement exclure certaines données à partir de ce Dernier et bien que liés, je pense qu'il est important de réaliser qu'ils sont en effet différents.
Une Idée
Qui dit que vous pouvez très facilement avoir une AutoMapper de configuration de Modèle -> ViewModel et un autre pour aller de EditModel -> Modèle. Puis les différentes actions du Contrôleur suffit d'utiliser AutoMapper. L'enfer de la EditModel pourraient avoir des fonctions de valider ses propriétés contre le modèle et l'application de ces valeurs pour le Modèle lui-même. C'est ne rien faire d'autre et que vous avez ModelBinders MVC à la carte à la Demande de la EditModel de toute façon.
Une Autre Idée
Au-delà que ce que je pensais récemment ce genre de travaux hors de l'idée d'un ActionModel est que ce que le client est l'affichage de retour pour vous est en fait la description de plusieurs actions de l'utilisateur effectué et pas juste une grosse boule de données. Ce serait certainement besoin d'un peu de Javascript, côté client, de gérer, mais l'idée est intrigante, je pense.
Essentiellement que l'utilisateur effectue des actions sur l'écran que vous avez présentée, Javascript serait de commencer à créer une liste d'objets d'action. Un exemple est, peut être, c'est à l'utilisateur une information sur les employés de l'écran. Ils mettent à jour le nom et ajouter une nouvelle adresse parce que l'employé a été récemment marié. Sous les couvertures de ce produit un ChangeEmployeeName
et AddEmployeeMailingAddress
objets d'une liste. L'utilisateur clique sur "Enregistrer" pour valider les modifications et vous soumettre la liste de deux objets, chacun contenant uniquement les informations nécessaires pour effectuer chaque action.
Vous avez besoin d'une plus intelligente ModelBinder puis celui par défaut mais bon sérialiseur JSON doit être en mesure de prendre soin de la cartographie du côté client, les objets d'action pour le côté serveur. Le côté serveur (si vous êtes dans un 2-tier de l'environnement) pourrait facilement avoir des méthodes qui ont terminé l'action sur le Modèle qu'ils travaillent avec. Ainsi, le Contrôleur de l'action se termine juste à l'obtention d'un Identifiant de l'instance du Modèle de pull et une liste d'actions à effectuer. Ou les actions que l'id d'eux pour les garder très distincte.
Alors peut-être quelque chose comme ceci est réalisée sur le côté serveur:
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
}
Que fait vraiment l'affichage d'action assez générique, puisque vous vous appuyez sur votre ModelBinder pour vous le bon IUserAction instance et votre IUserAction instance de la bonne logique elle-même, ou (plus probablement) appel dans le Modèle à l'info.
Si vous étiez dans un 3 niveau de l'environnement de la IUserAction pourrait juste être simple Otd être tiré à travers la frontière et réalisée de la même méthode sur l'application de la couche. En fonction de comment vous le faites que la couche peut être divisée en place très facilement et restent dans une transaction (ce qui vient à l'esprit est Agathe de requête/réponse et de prendre avantage de la DI et de NHibernate de la carte d'identité).
De toute façon je suis sûr que ce n'est pas une idée parfaite, il aurait besoin d'un peu de JS côté client à gérer, et je n'ai pas été capable de faire un projet qui reste encore à voir comment elle se déroule, mais le post a été en essayant de penser à comment faire pour y aller et revenir de nouveau, alors j'ai pensé que je voudrais donner à mes pensées. J'espère que cela aide, et j'aimerais entendre d'autres façons de gérer les interactions.