vista tutorial programacion paso net mvc modelo lenguaje form definicion controlador asp asp.net-mvc dynamic c#-4.0 typing viewpage

asp.net-mvc - programacion - mvc c# tutorial



Página de vista tipada dinámica (4)

es posible? Esto es lo que estoy intentando:

public ActionResult Index() { dynamic p = new { Name = "Test", Phone = "111-2222" }; return View(p); }

Y luego mi vista hereda de System.Web.Mvc.ViewPage<dynamic> e intenta imprimir Model.Name.

Me aparece un error: ''<> f__AnonymousType1.Name'' es inaccesible debido a su nivel de protección

Entonces, básicamente, ¿es lo que intento hacer simplemente imposible? ¿Por qué o por qué no?

Actualización: aquí está mi vista

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %> <asp:Content ...> <%=Model.Name%> <%=Model.Phone%> </asp:Content>

El constructor Vista está incorporado en el marco.


Los tipos anónimos no pueden ser devueltos por un método; solo son válidos dentro del alcance del método en el que están definidos.

Debe usar una clase Model que haya definido previamente y pasarla a su View. No hay nada de malo en pasar una clase de modelo que no tiene todos los campos definidos.

Actualización :

Creo que estaba equivocado antes. Esto debería funcionar. Tal vez el problema esté dentro de la Vista. ¿Puedes publicar más código? Especialmente la Vista y su constructor.

Actualiza el segundo:

Ok, me equivoqué al pasar un tipo anónimo a otro método para usarlo como variable dinámica, eso se puede hacer.

Pero también estaba equivocado en mi creencia de que lo que intentas hacer funcionaría. Desafortunadamente para ti, no lo hará. El problema es que está usando ViewPage<TModel> , que usa un ViewDataDictionary<TModel> internamente. Debido a que requieren tipos fuertes, no podrá usar objetos dinámicos con ellos. La estructura interna simplemente no usa dinámicamente internamente, y especifica dinámica a medida que el tipo falla.

Lo que se necesitaría es una clase DynamicViewPage y una clase DynamicViewPage correspondiente que acepte el object y lo guarde internamente como una dinámica. Entonces podría usar un tipo anónimo y pasarlo a sus Vistas.

Dicho eso, no ganarías nada. Sería capaz de especificar sus Vistas como lo ha hecho (es decir, <%=Model.Name%> ), pero no se beneficiaría de un tipado fuerte. No habría intellisense y no habría ningún tipo de seguridad. Haría bien en usar ViewDataDictionary sin tipo, como sugiere @Dennis Palmer.

Este ha sido un experimento de pensamiento interesante (y desafortunadamente para mí, absorbente), pero creo, finalmente, que no va a suceder. O declare un tipo público y páselo a sus Vistas, o use el diccionario sin tipo.


¿Qué beneficio espera obtener del uso del tipo dinámico aquí?

El uso del diccionario ViewData es una forma muy fácil de agregar objetos / elementos arbitrarios a su salida de vista.

No necesita reflexión para obtener los nombres de propiedad dentro de su Vista. Simplemente use ViewData.Keys para obtener la colección de nombres.

Editar: Acabo de aprender un poco más acerca de la dinámica y creo que tal vez necesites crear tu propia clase de objeto dinámico que herede de DynamicObject . TrySetMember tener un diccionario privado en esa clase y luego anular TrySetMember y TryGetMember .

Editar a un lado: creo que una ventaja de un modelo de vista fuertemente tipado es que puede aceptarlo como un parámetro en sus métodos de acción POST. El framework MVC manejará el enlace del modelo y en el método de acción simplemente tiene una instancia de su clase ViewModel. No creo que tengas esa ventaja con una dinámica, incluso si funcionan.

Editar resultado: Bueno, traté de usar una clase derivada de DynamicObject, pero VS2010 se bloquea cuando intenta renderizar la vista. No recibo ninguna excepción, solo un bloqueo y Visual Studio se reinicia. Aquí está el código que se me ocurrió que causa el colapso.

La clase dinámica personalizada:

public class DynViewModel : DynamicObject { private Dictionary<string, object> ViewDataBag; public DynViewModel() { this.ViewDataBag = new Dictionary<string, object>(); } public override bool TrySetMember(SetMemberBinder binder, object value) { this.ViewDataBag[binder.Name] = value; return true; } public override bool TryGetMember(GetMemberBinder binder, out object result) { result = this.ViewDataBag[binder.Name]; return true; } }

En el controlador:

public ActionResult DynamicView() { dynamic p = new DynamicViewModel.Models.DynViewModel(); p.Name = "Test"; p.Phone = "111-2222"; return View(p); }

Mi opinión es básicamente la misma que figura en la pregunta:

<p>Name: <%=Model.Name %></p> <p>Phone: <%=Model.Phone %></p>

Mi conclusión: Esto podría funcionar, pero en la versión beta 1 de VS2010 no puedo entender por qué mi código hace que Visual Studio se cuelgue. Lo intentaré de nuevo en VS2010 Beta 2 cuando se publique porque es un ejercicio interesante para aprender sobre dinámica. Sin embargo, incluso si esto funcionara, todavía no veo ninguna ventaja con respecto al uso del diccionario ViewData.

Phil Haack al rescate! Aquí hay una publicación de blog de Phil Haack que podría ayudarte. Parece que es lo que estabas buscando. Diversión con método perdido y C # 4


El error real aquí ( <>f__AnonymousType1.Name'' is inaccessible due to its protection level ) es el resultado del uso de tipos anónimos. Los tipos anónimos son implícitamente internal (al menos en C #), por lo tanto, solo se puede acceder normalmente desde el mismo ensamblado. Dado que su vista se compila en un ensamblaje separado en tiempo de ejecución, no puede acceder al tipo anónimo internal .

La solución es pasar clases concretas / nombradas como modelos a su vista. La vista en sí misma puede usar dynamic si lo desea.


En .NET 4.0, los tipos anónimos se pueden convertir fácilmente a ExpandoObjects y, por lo tanto, todos los problemas se solucionan con la sobrecarga de la conversión. Mira aquí