asp.net mvc - ventajas - Entidades EF vs. Modelos de servicio vs. Modelos de vista(MVC)
mvc ejemplos (3)
Estoy tratando de entender y encontrar buenas prácticas para diseñar sus modelos de aplicaciones / dominios (POCO / DTO).
Digamos que tengo la siguiente tabla de base de datos, Cuenta:
UserID int
Email varchar(50)
PasswordHash varchar(250)
PasswordSalt varchar(250)
Por supuesto, EF4 construiría la entidad así:
public class Account
{
public int UserID { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
public string PasswordSalt { get; set; }
}
Ahora, digamos que tengo un modelo de vista para registrar un nuevo usuario, que puede parecer algo así:
public class RegistrationViewModel
{
public string Email { get; set; }
public string Password { get; set; }
}
Por último, tengo un servicio que necesita registrar al usuario:
public class RegistrationService
{
public void RegisterUser(??? registration)
{
// Do stuff to register user
}
}
Estoy tratando de averiguar qué pasar en el método RegisterUser. El modelo de vista, por supuesto, se encuentra en mi aplicación web (capa de presentación), por lo que no quiero que esto pase a mi servicio.
Entonces, estoy pensando en una de las cuatro posibilidades:
1) Configure un modelo de servicio que sea similar, si no idéntico, al RegistrationViewModel, y use esto:
public class RegistrationServiceModel
{
public string Email { get; set; }
public string Password { get; set; }
}
public class RegistrationService
{
public void RegisterUser(RegistrationServiceModel registration)
{
// Do stuff to register user
}
}
2) Configure una interfaz del modelo, y herede esto en mi modelo de vista, y configure mi método para aceptar la interfaz:
public interface IRegistrationModel
{
string Email;
string Password;
}
public class RegistrationServiceModel : IRegistrationModel
{
public string Email { get; set; }
public string Password { get; set; }
}
public class RegistrationService
{
public void RegisterUser(IRegistrationModel registration)
{
// Do stuff to register user
}
}
3) Pase la entidad de Cuenta, haciendo el mapeo RegistrationViewModel-to-Account en mi controlador:
public class RegistrationService
{
public void RegisterUser(Account account)
{
// Do stuff to register user
}
}
4) Mover el modelo de mi vista fuera de la presentación a una capa de dominio / servicio y pasarlo al método de servicio:
public class RegistrationService
{
public void RegisterUser(RegistrationViewModel account)
{
// Do stuff to register user
}
}
Ninguno de estos tres escenarios parece ideal, ya que veo problemas en cada uno de ellos. Así que me pregunto si hay otro método que no pueda pensar.
¿Cuáles son las buenas prácticas para esto?
Gracias por adelantado.
En este caso, tiene mucho sentido utilizar un DTO (objeto de transferencia de datos). Puede crear una clase AccountDto
en la capa de servicio y usarla para pasar los datos de registro al servicio. Puede ser similar a ViewModel en algunos casos, pero en general puede mostrar mucho más en su Vista de lo que se requiere para crear un usuario. Para ilustrar aún más el punto, su ViewModel probablemente se verá algo como esto:
public class RegistrationViewModel
{
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }
[Required]
[Compare("Password")]
public string RepeatPassword { get; set; }
}
Mientras que su DTO solo requerirá las propiedades de Email
y Password
.
public class AccountDto
{
public string Email { get; set; }
public string Password { get; set; }
}
Como puede ver, el ViewModel
solo contiene los datos necesarios para la View
. La lógica de validación de correo electrónico y comparación de contraseñas ocurre en su capa web. Usted usa el DTO para obtener solo el correo electrónico y la contraseña del Servicio. Y luego, en la capa de servicio, hash la contraseña, completa tu objeto Entidad y conserva los valores en la base de datos.
Nunca pasas un modelo de vista al servicio. Un servicio ni siquiera conoce la existencia de un modelo de vista que podría haber definido en su nivel de presentación. Un servicio funciona con modelos de dominio.
Utilice Mapeador automático para asignar entre el modelo de vista y el modelo de dominio y viceversa.
Personalmente, nunca he oído hablar de modelos de servicio en DDD (ver modelos de servicios).
Utilice la tercera opción, seguro. Como dijo šljaker, el Servicio no debe tener en cuenta la parte de presentación de la aplicación (de la que forma parte ViewModel).
Claro, también, no complique demasiado las cosas incluyendo toneladas de modelos de transición como RegistrationServiceModel
o, aún peor, IRegistrationModel
(el último llevará a una "explosión de interfaz" algún día).
Asi que:
- Tener una entidad de dominio (entidad POCO que se mantiene con Entity Framework o NHibernate o NoRM o lo que sea).
- Tenga un ViewModel que represente su modelo de dominio en un contexto dado. No dude en hacer un
ViewModel
por Acción de Controlador si es necesario. El beneficio de los efectos secundarios de los ViewModels estrictos (aquellos que están 1: 1 con su Vista) es la ausencia total de problemas de publicación excesiva y baja. Depende de su situación concreta / gusto sin embargo. - Use los atributos de DataAnnotation con sus ViewModels para proporcionar una validación básica (recuerde que también debe validar las reglas de negocios, pero debería estar detrás del cable, dentro de la capa de Servicios / Repositorios).
- No dejes que el Servicio de aplicaciones se entere de ViewModels. Cree una instancia de entidad de dominio y aliméntela al Servicio en su lugar (para validar / persistir).
- Use AutoMapper como una opción para mapear rápidamente desde sus entidades de dominio a ViewModels.
- Asigne desde
ViewModel
oFormCollection
a su entidad, ya sea en la acción Controlador o enIModelBinder
personalizado. - (Opcionalmente) Recomiendo seguir el Principio de Thunderdome . Es un uso realmente muy conveniente de ViewModels.