2010-01-05 22 views
8

Mi terminología probablemente esté muy lejos de aquí, pero básicamente estoy tratando de pasar múltiples modelos de datos a una vista. Para ayudar a poner la pregunta en contexto, tome este ejemplo:Múltiples modelos enviados a una sola instancia de vista

Digamos que estaba haciendo un blog. Cuando inicio sesión, deseo que la pantalla de inicio muestre una lista de todos los comentarios nuevos no aprobados, así como una lista de usuarios recientemente registrados y una lista de las publicaciones de blog enviadas más recientemente.

La mayoría de las discusiones que he visto sugieren escribir fuerte la página de vista para que se pueda invocar con algo como "return View (RecentComments)" y repetir los comentarios en la vista, o para convertir el modelo de datos como "var NewUsers = (MembershipUserCollection) ViewData.Model ". Lo que más me apetece es la forma "correcta", o al menos "adecuada", de pasar varios modelos manteniendo la separación lógica adecuada.

+0

* suspiro * en retrospectiva, esto es vergonzosamente obvio ... – nathanchere

Respuesta

14

Una forma es crear un nuevo tipo que encapsula las dos piezas de datos del modelo:

public class MyBigViewData { 
    public SubData1 SubData1 { get; set; } 
    public SubData2 SubData2 { get; set; } 
} 

public class SubData1 { 
    ... more properties here ... 
} 

public class SubData2 { 
    ... more properties here ... 
} 

Otra forma consiste en almacenar los "principales" datos del modelo como los datos de tipo fuerte y almacenar otros datos de la ver datos como elementos del diccionario:

ViewData["username"] = "joe"; // "other" data 
ViewData["something"] = "whatever"; // "other" data 
ViewData["subdata1"] = new SubData1(...); 
return View(myRealModelData); 

la ventaja del segundo método es que no es necesario hacer nada especial en absoluto: funciona nada más sacarlo de la caja.

+0

Haría lo más simple que podría funcionar aquí, así que almacene los datos en la colección ViewData. Fácil. –

+1

El problema con este enfoque es que puede terminar con una proliferación de modelos de vista para cada vista. Algunos argumentan que así es como debe ser, y en un mundo perfecto, estoy de acuerdo, pero muchas veces este grado de personalización excede los requisitos y realmente puede hacer que el proyecto sea más difícil de comprender. Un enfoque más rápido, pero ** potencialmente riesgoso **, sería usar mis respuestas a continuación con las entidades de tu dominio. En algunos entornos, esto es inaceptable. Por ejemplo, si externaliza el desarrollo de su vista, es posible que no desee que sus entidades sean visibles o inviables desde la vista. –

3

Lamentablemente, la única forma de lograr el paso de varios objetos es creando un objeto con ambos objetos como campos/propiedades, o usando una matriz débilmente tipada.

3

La manera de pasar varios modelos a una vista es crear lo que llamamos un Modelo de vista de formulario que tiene sus otros modelos dentro de él.

Luego en su vista puede pasar los modelos individuales contenidos en su Modelo de vista de formulario a las Vistas parciales responsables de representar los datos en dichos modelos.

Tiene sentido?

edición

por cierto: un modelo de formulario de vista es simplemente una clase. no es un tipo especial como puede haber sido sugerido por mi respuesta.

+2

El término es 'ViewModel' Lo llamó' FormViewModel' porque el usuario estaba completando un 'Form'. Si no está completando un formulario, entonces es simplemente un 'ViewModel' y eso permite pasar objetos fuertemente tipados en lugar de cadenas mágicas. –

+0

Nice one @George. – griegs

8

Lo que he hecho en el pasado es escribir una clase que contenía instancias de ambas clases que necesitaré en la vista.

es decir

public class City{ 
public Mall TheMall; 
public School TheSchool; 
} 

Entonces su vista será fuertemente tipado como ciudad, y que va a utilizar y Model.TheMall.Property Model.TheSchool.Property acceder a lo que necesita

EDITAR

Este es un ejemplo de lo que significan otros carteles al crear un objeto con ambos objetos como campos/propiedades

1

Después de trabajar en una gran aplicación ASP.NET MVC, encontré que el enfoque que era más productivo a la vez que minimizaba el tiempo de ejecución se basaba en el uso de genéricos para imitar la estructura anidada de vistas. Esencialmente, las vistas obtienen su propio tipo de datos.Normalmente, estos son objetos de dominio o colecciones de objetos de dominio que incluyen metadatos. Las versiones genéricas de estos tipos están disponibles en todas las páginas maestras posibles, tomando un parámetro de tipo que define los datos relevantes para la página maestra.

public class Car { 
    // can be used as a model 
} 

public class CarCollection: Collection<Car> { 
    public BodyTypes BodyType {get;set;} 
    public Colors Color {get;set;} 
    // can also be used as a model 
} 

public interface ILayoutModel<TLayout> { 
    TLayout LayoutModel {get;set;} 
} 

public class CarView<TLayout>: Car, ILayoutModel<TLayout> { 
    // model that can be used with strongly-typed master page 
} 

public class CarCollection<TLayout> : CarCollection, ILayoutModel<TLayout> { 
    // model that can be used with strongly-typed master page 
} 

public class LayoutAData { 
    // model for LayoutA.master 
} 

public class LayoutBData { 
    // model for LayoutB.master 
} 

También es posible invertir la genérico-dad, pero desde el punto de vista dicta la disposición, los datos de vista debe dominar sobre los datos de diseño en mi opinión. LayoutA.master derivaría de ViewMasterPage<ILayoutModel<LayoutAData>> y LayoutB.master derivaría de ViewMasterPage<ILayoutModel<LayoutBData>>. Esto mantiene los datos de vista y los datos de diseño separados, de una manera consistente, fuertemente tipada y flexible.

2

Además de mi otra respuesta, otra forma de hacerlo sería no escribir con fuerza la vista y las páginas maestras en la directiva de página, sino utilizar las extensiones genéricas ViewData basadas en tipo desde MVC Contrib. Estas extensiones utilizan básicamente el nombre de tipo completo como la clave del diccionario ViewData. Efectivamente, los beneficios de tipeo son los mismos que los de la página fuertemente tipada, con menos sobrecarga de clases en términos de la cantidad de clases de modelos de vista requeridas. Luego, en sus acciones que haces

ViewData.Add<Car>(car); 
ViewData.Add<LayoutAData>(layoutAData); 

y en las vistas que usted

<%= ViewData.Get<Car>().Color %> 

y en la página maestra que haces

<%= ViewData.Get<LayoutAData>().Username %> 

Se puede almacenar en caché estos se <> Llamadas en línea en las vistas para mitigar el costo del casting varias veces.

1

Crear un objeto que pueda encapsular sus otros objetos es la mejor manera de hacerlo. De lo contrario, estás atascado con un montón de etiquetas feas de ViewData en el controlador y la vista.

1

Una cosa que nadie parece haber mencionado es que en el ejemplo de las preguntas originales, podría tener sentido crear la vista a partir de una serie de acciones secundarias que manejan su propia área de funcionalidad en lugar de crear un modelo mega view. De esta forma, los componentes tales como los mensajes no aprobados, etc. pueden reutilizarse.

Esto también proporciona una mejor encapsulación.

Cuestiones relacionadas