A partir de esta pregunta , parece que tiene sentido que un controlador cree un ViewModel que refleje con mayor precisión el modelo que la vista está tratando de mostrar, pero tengo curiosidad por algunas de las convenciones (soy nuevo en el patrón MVC , si ya no fuera obvio).
Básicamente, tuve las siguientes preguntas:
- Normalmente me gusta tener una clase / archivo. ¿Tiene sentido esto con un ViewModel? si solo se está creando para transferir datos de un controlador a una vista?
- Si un ViewModel pertenece a su propio archivo y está utilizando una estructura de directorio / proyecto para mantener las cosas separadas, ¿a dónde pertenece el archivo ViewModel ? En el directorio de controladores ?
Eso es básicamente todo por ahora. Es posible que tenga algunas preguntas más por venir, pero esto me ha estado molestando durante la última hora más o menos, y parece que puedo encontrar una guía constante en otros lugares.
EDITAR: Al mirar la aplicación NerdDinner de muestra en CodePlex, parece que los ViewModels son parte de los Controladores , pero todavía me incomoda que no estén en sus propios archivos.
asp.net-mvc
asp.net-mvc-viewmodel
Jerhinesmith
fuente
fuente
Respuestas:
Creo lo que llamo un "ViewModel" para cada vista. Los puse en una carpeta llamada ViewModels en mi proyecto web MVC. Los nombro después del controlador y la acción (o vista) que representan. Entonces, si necesito pasar datos a la vista Registrarse en el controlador de Membresía, creo una clase MembershipSignUpViewModel.cs y la pongo en la carpeta ViewModels.
Luego agrego las propiedades y métodos necesarios para facilitar la transferencia de datos desde el controlador a la vista. Utilizo el Automapper para pasar de mi ViewModel al Modelo de dominio y viceversa si es necesario.
Esto también funciona bien para ViewModels compuestos que contienen propiedades que son del tipo de otros ViewModels. Por ejemplo, si tiene 5 widgets en la página de índice en el controlador de membresía y creó un ViewModel para cada vista parcial, ¿cómo pasa los datos de la acción Index a los parciales? Agregue una propiedad al MembershipIndexViewModel de tipo MyPartialViewModel y al representar el parcial pasaría en Model.MyPartialViewModel.
Hacerlo de esta manera le permite ajustar las propiedades parciales de ViewModel sin tener que cambiar la vista de índice. Todavía pasa en Model.MyPartialViewModel, por lo que hay menos posibilidades de que tenga que pasar por toda la cadena de parciales para arreglar algo cuando todo lo que está haciendo es agregar una propiedad al ViewModel parcial.
También agregaré el espacio de nombres "MyProject.Web.ViewModels" al web.config para permitirme hacer referencia a ellos en cualquier vista sin tener que agregar una declaración de importación explícita en cada vista. Solo lo hace un poco más limpio.
fuente
Separar clases por categoría (Controladores, ViewModels, Filtros, etc.) no tiene sentido.
Si desea escribir código para la sección Inicio de su sitio web (/), cree una carpeta llamada Inicio y coloque el HomeController, IndexViewModel, AboutViewModel, etc. y todas las clases relacionadas utilizadas por las acciones de Inicio.
Si ha compartido clases, como un ApplicationController, puede ponerlo en la raíz de su proyecto.
¿Por qué separar las cosas que están relacionadas (HomeController, IndexViewModel) y mantener las cosas juntas que no tienen ninguna relación (HomeController, AccountController)?
Escribí una publicación de blog sobre este tema.
fuente
Mantengo mis clases de aplicación en una subcarpeta llamada "Core" (o una biblioteca de clases separada) y utilizo los mismos métodos que el aplicación de muestra KIGG pero con algunos pequeños cambios para que mis aplicaciones sean más SECAS.
Creo una clase BaseViewData en / Core / ViewData / donde almaceno propiedades comunes de todo el sitio.
Después de esto, también creo todas mis clases ViewData de vista en la misma carpeta que luego derivan de BaseViewData y tienen propiedades específicas de vista.
Luego creo un ApplicationController del que derivan todos mis controladores. ApplicationController tiene un método genérico GetViewData de la siguiente manera:
Finalmente, en mi acción Controlador, hago lo siguiente para construir mi Modelo ViewData
Creo que esto funciona muy bien y mantiene sus vistas ordenadas y sus controladores delgados.
fuente
Una clase ViewModel está ahí para encapsular múltiples piezas de datos representados por instancias de clases en un objeto fácil de administrar que puede pasar a su Vista.
Tendría sentido tener sus clases ViewModel en sus propios archivos, en el propio directorio. En mis proyectos tengo una subcarpeta de la carpeta Modelos llamada ViewModels. Ahí es donde viven mis ViewModels (por ejemplo
ProductViewModel.cs
).fuente
No hay un buen lugar para guardar sus modelos. Puede mantenerlos en ensamblaje separado si el proyecto es grande y hay muchos ViewModels (Objetos de transferencia de datos). También puede guardarlos en una carpeta separada del proyecto del sitio. Por ejemplo, en Oxite se colocan en el proyecto Oxite que también contiene muchas clases diferentes. Los controladores en Oxite se mueven a proyectos separados y las vistas también están en proyectos separados.
En CodeCampServer ViewModels se denominan * Form y se colocan en el proyecto de IU en la carpeta Modelos.
En MvcPress proyecto , se colocan en el proyecto de datos, que también contiene todo el código para trabajar con la base de datos y un poco más (pero no recomendé este enfoque, es solo para una muestra)
Entonces puedes ver que hay muchos puntos de vista. Por lo general, mantengo mis ViewModels (objetos DTO) en el proyecto del sitio. Pero cuando tengo más de 10 modelos, prefiero moverlos para ensamblarlos por separado. Por lo general, en este caso, también estoy moviendo los controladores para separar el ensamblaje.
Otra pregunta es cómo asignar fácilmente todos los datos del modelo a su ViewModel. Sugiero echar un vistazo a la biblioteca AutoMapper . Me gusta mucho, hace todo el trabajo sucio para mí.
Y también sugiero mirar el proyecto SharpArchitecture . Proporciona muy buena arquitectura para proyectos y contiene muchos marcos y guías geniales y una gran comunidad.
fuente
Aquí hay un fragmento de código de mis mejores prácticas:
fuente
Lanzamos todos nuestros ViewModels en la carpeta Modelos (toda nuestra lógica de negocios está en un proyecto separado de ServiceLayer)
fuente
Personalmente, sugeriría si ViewModel es cualquier cosa menos trivial, luego use una clase separada.
Si tiene más de un modelo de vista, le sugiero que tenga sentido dividirlo en al menos un directorio. si el modelo de vista se comparte más tarde, el espacio de nombre implícito en el directorio facilita el traslado a un nuevo ensamblado.
fuente
En nuestro caso, tenemos los Modelos junto con los Controladores en un proyecto separado de las Vistas.
Como regla general, hemos tratado de mover y evitar la mayoría de las cosas de ViewData ["..."] al ViewModel, por lo tanto, evitamos los castings y las cadenas mágicas, lo cual es algo bueno.
ViewModel también contiene algunas propiedades comunes, como información de paginación para listas o información de encabezado de la página para dibujar migas de pan y títulos. En este momento, la clase base contiene demasiada información en mi opinión y podemos dividirla en tres partes, la información más básica y necesaria para el 99% de las páginas en un modelo de vista base, y luego un modelo para las listas y un modelo para los formularios que contienen datos específicos para esos escenarios y heredan de la base.
Finalmente, implementamos un modelo de vista para cada entidad para manejar la información específica.
fuente
código en el controlador:
código en el modelo de vista:
proyectos:
DevJet.Web (el proyecto web ASP.NET MVC)
DevJet.Web.App.Dictionary (un proyecto separado de la Biblioteca de clases)
en este proyecto, hice algunas carpetas como: DAL, BLL, BO, VM (carpeta para ver modelos)
fuente
Cree una clase base de modelo de vista que comúnmente requiera propiedades como el resultado de la operación y los datos contextuales, también puede colocar datos y roles de usuario actuales
En la clase de controlador base, tenga un método como PopulateViewModelBase (), este método llenará los datos contextuales y los roles de usuario. HasError y ErrorMessage, configure estas propiedades si hay una excepción al extraer datos del servicio / db. Enlace estas propiedades a la vista para mostrar el error. Los roles de usuario se pueden usar para mostrar la sección oculta en la vista en función de los roles.
Para rellenar modelos de vista en diferentes acciones de obtención, puede hacerse coherente al tener un controlador base con el método abstracto FillModel
En controladores
fuente