2008-10-21 26 views
39

Acabo de empezar a trabajar con ASP.NET MVC ahora que está en versión beta. En mi código, estoy ejecutando una consulta LINQ a SQL simple para obtener una lista de resultados y pasar eso a mi vista. Este tipo de cosas:¿Puedo pasar un tipo anónimo a mi vista ASP.NET MVC?

var ords = from o in db.Orders 
      where o.OrderDate == DateTime.Today 
      select o; 

return View(ords); 

Sin embargo, en mi opinión, me di cuenta que había necesidad de tener acceso a nombre del cliente para cada orden. Empecé a usar o.Customer.Name pero estoy bastante seguro de que esto está ejecutando una consulta separada para cada orden (debido a la carga diferida de LINQ).

La forma lógica de reducir el número de consultas sería seleccionar el nombre del cliente al mismo tiempo. Algo como:

var ords = from o in db.Orders 
      from c in db.Customers 
      where o.OrderDate == DateTime.Today 
       and o.CustomerID == c.CustomerID 
      select new { o.OrderID, /* ... */, c.CustomerName }; 

return View(ords); 

Excepto que ahora mi variable "ords" es un IEnumerable de tipo anónimo.

¿Es posible declarar una vista MVC de ASP.NET de forma que acepte un IEnumerable como su datos de vista donde T se define por lo que pasa desde el controlador, o tendré que definir un tipo concreto para poblar de mi consulta?

Respuesta

22

¿Puede pasarlo a la vista? Sí, pero su vista no estará fuertemente tipada. Pero los ayudantes funcionarán. Por ejemplo:

public ActionResult Foo() { 
    return View(new {Something="Hey, it worked!"}); 
} 

//Using a normal ViewPage 

<%= Html.TextBox("Something") %> 

Ese cuadro de texto debería mostrar "¡Oye, funcionó!" como el valor.

Entonces, ¿puede definir una vista donde T se define por lo que le pasa desde el controlador? Bueno, sí, pero obviamente no en compilación.

Piénselo un momento. Cuando declaras un tipo de modelo para una vista, obtienes inteligencia para la vista. Eso significa que el tipo debe determinarse en el momento de la compilación. Pero la pregunta es: ¿podemos determinar el tipo de algo que se le da en el tiempo de ejecución? Claro, pero no con fuerte tipeado preservado.

¿Cómo conseguiría Intellisense para un tipo que aún no conoce? El controlador podría terminar pasando cualquier tipo a la vista mientras está en tiempo de ejecución. Ni siquiera podemos analizar el código y adivinar, porque los filtros de acción podrían cambiar el objeto pasado a la vista por todo lo que sabemos.

Espero que aclare la respuesta sin ofuscarla más.:)

+0

Si alguien sabe que serías tú, Phil. ¡Gracias por ser tan accesible a la plebe como yo! –

+0

¿Respondió esto a la pregunta? Tengo este problema exacto y esta respuesta no ayuda. ¿Podrías mostrarnos cómo podemos recorrer los ords y mostrarlos en una vista? –

+11

¡No responde la pregunta! Sorprendentemente, funciona para el cuadro de texto, pero si solo quería mostrar este valor, ¿cómo lo hago? <% = Model.Something%> no funciona, obtendrá 'object' no contiene una definición para la excepción 'Something'. – PawelRoman

0

puede pasar un Objeto y utilizar la reflexión para obtener los resultados deseados. Eche un vistazo a ObjectDumper.cs (incluido en csharpexamples.zip) para ver un ejemplo de esto.

+0

Sí, estaba pensando que el uso de la reflexión para descifrar el tipo anónimo abierto y tratarlo como un Dictionary podría ser la única solución. Un poco fastidioso si ese es el caso. –

0

Si no me equivoco, los tipos anónimos se convierten en objetos muy tipados en tiempo de compilación. Sin embargo, si el objeto fuertemente tipado es válido para ver datos es otra pregunta.

1

Este post muestra cómo puede devolver un tipo anónimo desde un método, pero no va a satisfacer sus requisitos.

Otra opción puede ser convertir el tipo anónimo en JSON (JavaScriptSerializer lo hará) y luego devolver ese JSON a la vista, entonces necesitaría algo de jQuery, etc. para hacer lo que quiera con él.

He estado utilizando Linq para "dar forma" a mis datos en un formato JSON que mi vista necesita con gran éxito.

+0

La idea de JSON suena intrigante, pero si voy a agregar código para hacerlo, entonces también podría definir una clase que tenga mi orden y las propiedades del cliente y abandonar la idea de tipo anónimo. +1 de todos modos. –

+0

de acuerdo. Mi escenario de uso de JSON principal ha sido devolver un objeto JSON de una llamada ajax que se utiliza para rellenar una cuadrícula (por ejemplo, Flexigrid), la cuadrícula requiere los datos en un formato particular, Linq rocas para ayudarme a dar forma a los datos en ese formato. – zadam

4

Por lo que vale, esta noche descubrí la clase DataLoadOptions y su método LoadWith. Pude decirle a mi LINQ to SQL DataContext que siempre cargue una fila de clientes cada vez que se recupera una fila de pedidos, por lo que la consulta original ahora obtiene todo lo que necesito en un solo golpe.

+0

Wow ... Muchas gracias. He estado buscando esto frenéticamente durante las últimas horas. Sabía que debía existir, pero no estaba seguro de dónde mirar. ¡Gracias hombre! –

1

Puede escribir una clase con las mismas propiedades de su tipo anónimo, y puede convertir su tipo anónimo en su tipo escrito a mano. El inconveniente es que tiene que actualizar la clase cuando realiza cambios de proyección en su consulta de linq.

+1

Eso luego derrota por completo el propósito de usar un tipo anónimo del método de acción. En ese punto, es mejor que devuelva una instancia de clase. – Peter

0

Estoy con el mismo problema ... después de pensar un poco, llegué a la conclusión de que la solución más correcta y más escalable, es serializar este tipo anónimo antes de enviarlo a la Vista. Por lo tanto, puede usar el mismo método para llenar la página usando el código Ver detrás y llenar su página usando JSON

11

Usted puede pasar tipos anónimos a una vista, simplemente recuerde lanzar el modelo a una dinámica.

Se puede hacer así:

return View(new { 
    MyItem = "Hello", 
    SomethingElse = 42, 
    Third = new MyClass(42, "Yes") }) 

En la parte superior de la vista que se puede hacer esto (el uso de la maquinilla de afeitar aquí)

@{ 
    string myItem = (dynamic)Model.MyItem; 
    int somethingElse = (dynamic)Model.SomethingElse; 
    MyClass third = (dynamic)Model.Third; 
} 

O puede echarlos de la ViewData como esto :

@{ 
    var myItem = ViewData.Eval("MyItem") as string 
    var somethingElse = ViewData.Eval("SomethingElse") as int? 
    var third = ViewData.Eval("Third") as MyClass 
} 
+7

Bueno, su primer ejemplo no funciona. Al menos no en MVC3. ¡Sorpresa! En primer lugar, en vistas sin tipo, 'Model' ya es' dynamic', no es necesario lanzarlo. Y segundo, con su código, obtengo una 'RuntimeBinderException' con el mensaje" * 'object' no contiene una definición de MyItem * ". ¿Algunas ideas? –

+5

Acabo de desenterrar una explicación. Resulta que los tipos anónimos son internos, lo que significa que sus propiedades no se pueden ver fuera de su ensamblado de definición. Eche un vistazo aquí: http://www.gregshackles.com/2010/09/anonymous-view-models-in-asp-net-mvc-using-dynamics/ –

6

en .NET 4.0 los tipos anónimos se pueden convertir fácilmente a ExpandoObjects y por lo tanto todo el probl EMS se fija con la sobrecarga de la conversión misma. Salida here

3

Here es un artículo que explica el paso del tipo Anónimo a Vistas y vincula los datos.

Gracias

Cuestiones relacionadas