Me gustaría decir que reutiliza el término ViewModel para ambas direcciones de la interacción del cliente. Si ha leído suficiente código ASP.NET MVC en la naturaleza, probablemente haya visto la distinción entre un modelo de vista y un modelo de edición. Pienso que es importante.
Un ViewModel representa toda la información necesaria para representar una vista. Esto podría incluir datos que se procesan en lugares no interactivos estáticos y también datos puramente para realizar una comprobación para decidir qué representar exactamente. Una acción Controller GET generalmente es responsable de empaquetar ViewModel para su Vista.
Un modelo de edición (o tal vez un modelo de acción) representa los datos necesarios para realizar la acción que el usuario quería hacer para esa POST. Entonces, EditModel realmente está tratando de describir una acción. Esto probablemente excluirá algunos datos del ViewModel y, aunque relacionado, creo que es importante darse cuenta de que son realmente diferentes.
Una Idea
Dicho esto fácilmente se podría tener una configuración AutoMapper para ir de Modelo -> modelo de vista y otro diferente para pasar de EditModel -> Modelo. Entonces las diferentes acciones del Controlador solo necesitan usar AutoMapper. Hell the EditModel podría tener funciones para validar sus propiedades contra el modelo y aplicar esos valores al mismo modelo. No está haciendo nada más y tiene ModelBinders en MVC para mapear la Solicitud al EditModel de todos modos.
Otra idea
Más allá de eso algo que he estado pensando recientemente ese tipo de obras de la idea de un ActionModel es que lo que el cliente es la publicación de nuevo a usted es en realidad la descripción de varias acciones del usuario realizado y no solo una gran cantidad de datos. Esto ciertamente requeriría algo de Javascript en el lado del cliente para administrar, pero la idea es intrigante, creo.
Esencialmente, como el usuario realiza acciones en la pantalla que usted ha presentado, Javascript comenzaría a crear una lista de objetos de acción. Un ejemplo es posiblemente que el usuario esté en una pantalla de información del empleado. Actualizan el apellido y agregan una nueva dirección porque el empleado se ha casado recientemente. Bajo las cubiertas esto produce un ChangeEmployeeName
y un AddEmployeeMailingAddress
objetos a una lista. El usuario hace clic en 'Guardar' para confirmar los cambios y usted envía la lista de dos objetos, cada uno con la información necesaria para realizar cada acción.
Necesitaría un ModelBinder más inteligente que el predeterminado, pero un buen serializador JSON debería ser capaz de encargarse de la asignación de los objetos de acción del lado del cliente a los del lado del servidor. Las del lado del servidor (si se encuentra en un entorno de 2 niveles) podrían tener fácilmente métodos que completen la acción en el Modelo con el que trabajan. Entonces, la acción del Controlador termina obteniendo un Id para que la instancia del Modelo lo extraiga y una lista de acciones para realizar en él. O las acciones tienen la identificación en ellos para mantenerlos muy separados.
Así que tal vez algo como esto se realiza en el lado del servidor:
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 realmente hace que la publicación posterior acción bastante genérico, ya que está confiando en su ModelBinder para conseguir que la instancia IUserAction correcta y la instancia IUserAction para realizar la lógica correcta o (más probable) llamar al Modelo con la información.
Si estuvieras en un entorno de 3 niveles, IUserAction podría simplemente convertirse en DTO simples que se filmarían a través del límite y se realizarían de forma similar en la capa de la aplicación. Dependiendo de cómo se haga esa capa, podría dividirse fácilmente y permanecer en una transacción (lo que le viene a la mente es la solicitud/respuesta de Agatha y aprovechar el mapa de identidad de DI y NHibernate).
De todos modos estoy seguro de que no es una idea perfecta, requeriría un poco de JS en el lado del cliente para gestionarlo, y no he podido hacer un proyecto para ver cómo se desarrolla, pero el post estaba tratando de pensar en cómo llegar y volver, así que pensé que iba a dar mis pensamientos. Espero que ayude y me gustaría saber de otras formas de gestionar las interacciones.
no estoy seguro AutoMapper es útil aquí, ya que no puede revertir el aplanamiento. Después de todo, el Modelo de Dominio no es un DTO simple como el Modelo de Vista, por lo tanto, puede no ser suficiente asignarle algunas propiedades. Probablemente, algunas acciones se deben realizar contra el Modelo de Dominio según el contenido del Modelo de Vista. Sin embargo, +1 para compartir un enfoque bastante bueno. –
@Anton ValueInjecter puede revertir el aplanamiento;) – Omu
con este enfoque no se mantiene delgado el controlador, viola SoC y DRY ... como Omu mencionó que debe tener una capa separada que se encargue de las tareas de mapeo. – Rookian