vista una que parcial net mvc example asp asp.net-mvc renderpartial

asp.net mvc - una - ¿Taquigrafía para crear un ViewDataDictionary con un modelo y elementos ViewData?



renderaction mvc (5)

Creé un método de extensión en HtmlHelper para copiar los nombres de propiedades y los valores de un objeto anónimo a un ViewDataDictionary.

Muestra

Html.RenderPartial("SomePartialView", MyModelObject, new { SomeDisplayParameter = true })

Extensión HtmlHelper

public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, object model, object viewData) { var vdd = new ViewDataDictionary(model); foreach (var property in viewData.GetType().GetProperties()) { vdd[property.Name] = property.GetValue(viewData); } htmlHelper.RenderPartial(partialViewName, vdd); }

¿Hay alguna forma de crear un ViewDataDictionary con un modelo y propiedades adicionales con una sola línea de código? Estoy tratando de hacer una llamada RenderPartial a una vista fuertemente tipificada al ensamblar tanto el modelo como algunas propiedades de configuración de pantalla adicionales sin ensamblar explícitamente el ViewDataDictionary en varias líneas. Parece que sería posible dada la sobrecarga RenderPartial toma tanto un object modelo como un ViewDataDictionary pero parece que simplemente ignora el ViewDataDictionary cuando ambos se completan.

// FAIL: This will result in ViewData being a ViewDataDictionary // where Model = MyModelObject and there are no other parameters available. this.Html.RenderPartial("SomePartialView", MyModelObject, new ViewDataDictionary(new { SomeDisplayParameter = true }));

Encontré a alguien más con el mismo problema , pero su solución es el mismo concepto multilínea que encontré: cree un ViewDataDictionary discreto con el modelo, agregue los nuevos parámetros y utilícelos en la llamada RenderPartial .

var SomeViewData = new ViewDataDictionary(MyModelObject); SomeViewData.Add("SomeDisplayParameter", true); this.Html.RenderPartial("SomePartialView", SomeViewData);

Siempre puedo ChainedAdd esa lógica en un método ChainedAdd que devuelve un diccionario duplicado con el nuevo elemento agregado, pero parece que me falta alguna forma de crear un ViewDataDictionary que haría esto por mí (y eso es un poco más general que yo estaba esperando).

this.Html.RenderPartial("SomePartialView", new ViewDataDictionary(MyModelObject).ChainedAdd("SomeDisplayParameter", true)); public static ViewDataDictionaryExtensions { public static ViewDataDictionary ChainedAdd(this ViewDataDictionary source, string key, object value) { return source.ChainedAdd(new KeyValuePair<string,object>(key, value)); } public static ViewDataDictionary ChainedAdd(this ViewDataDictionary source, KeyValuePair<string, object> keyAndValue) { ViewDataDictionary NewDictionary = new ViewDataDictionary(source); NewDictionary.Add(keyAndValue); return NewDictionary; } }

Además, al intentar ensamblar un ViewDataDictionary con un Model y ModelState explícitos, simplemente se genera un error de compilación porque el ModelState es de solo lectura.

// FAIL: Compilation error this.Html.RenderPartial("SomePartialView", new ViewDataDictionary { Model = MyModelObject, ModelState = new ViewDataDictionary( new { SomeDisplayParameter = true }});

RESPUESTA (S): Parece que Craig y yo terminamos encontrando dos sintaxis separadas que harán el trabajo. Definitivamente estoy sesgado en este caso, pero me gusta la idea de configurar el modelo primero y "decorarlo" después.

new ViewDataDictionary(MyModelObject) { { "SomeDisplayParameter", true }, { "SomeOtherParameter", 3 }, { "SomeThirdParameter", "red" } }; new ViewDataDictionary(new ViewDataDictionary() { {"SomeDisplayParameter", true }}) { Model = MyModelObject };

Por supuesto, todavía estaría girando mis ruedas sin su respuesta [finalmente puntual], por lo que, el círculo obtiene el cuadrado.


Esto es lo que funcionó para mí en el viejo estilo mvc aspx view:

<% Html.RenderPartial("ContactPartial", Model.ContactFactuur, new ViewDataDictionary(this.ViewData ) { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "Factuur" } }); %>

Lo que ocurre aquí es que en el constructor uso el viewdata actual "nuevo ViewDataDictionary (this.ViewData)", que es un viewdatadictionary que contiene el estado del modelo que necesito para los mensajes de validación.


Use un inicializador de objetos y inicializadores de colección:

new ViewDataDictionary(new ViewDataDictionary() { {"SomeDisplayParameter", true }}) { Model = MyModelObject }

El ViewDataDictionary interno obtiene su colección inicializada, luego esto rellena el ViewDataDictionary "real" usando la sobrecarga del constructor que toma ViewDataDictionary en lugar de un objeto. Finalmente, el inicializador de objetos establece el modelo.

Luego simplemente pase todo el conjunto sin configurar MyModelObject por separado:

this.Html.RenderPartial("SomePartialView", null, new ViewDataDictionary(new ViewDataDictionary() { {"SomeDisplayParameter", true }}) { Model = MyModelObject });


Utilizando la respuesta de Craig como punto de partida, ni siquiera sabía que podría combinar una llamada de constructor y un inicializador de objetos. Me topé con este snippet de Palermo que conduce a una combinación que funciona. Utiliza algún tipo de diccionario abreviado que de alguna manera termina poblando ModelState cuando lo consume el inicializador de objetos ViewDataDictionary.

new ViewDataDictionary(MyModelObject) { { "SomeDisplayParameter", true }, { "SomeOtherParameter", 3 }, { "SomeThirdParameter", "red" } }; // Of course, this also works with typed ViewDataDictionary objects (what I ended up using) new ViewDataDictionary<SomeType>(MyModelObject) { { "SomeDisplayParameter", true }, { "SomeOtherParameter", 3 }, { "SomeThirdParameter", "red" } };

Todavía no veo cómo funciona esto dado que no puede establecer ModelState explícitamente en un inicializador, pero parece mantener tanto el objeto del modelo original como los parámetros "anexados" para la vista. Definitivamente, hay una serie de otras permutaciones de esta sintaxis que no funcionan (no puede combinar el modelo con el diccionario en un solo objeto o usar la sintaxis del inicializador de objetos para los valores del diccionario), pero la versión anterior parece funcionar.


Vine aquí con la misma pregunta.

Lo que pensé que podría funcionar era esto (perdón por la sintaxis de VB Razor)

@Code Html.RenderPartial("Address", Model.MailingAddress, New ViewDataDictionary(New With {.AddressType = "Mailing Address"}))End Code

Pero, por supuesto, obtienes este error en tiempo de ejecución:

System.InvalidOperationException no fue manejado por el código de usuario

Mensaje = El elemento modelo que se pasó al diccionario es del tipo ''VB $ AnonymousType_1`1 [System.String]'', pero este diccionario requiere un elemento modelo del tipo ''ViewModel.Address''.

Pero lo que encontré, es que lo que realmente quería era usar la Plantilla de Editor de todos modos.

En lugar del uso de RenderPartial:

@Html.EditorFor(Function(model) model.MailingAddress, "Address", New With {.AddressType = "Mailing Address"})

Una plantilla de editor es solo una vista parcial que vive

~ / Views / {Model | Shared} /EditorTemplates/templatename.vbhtml

Mi plantilla para Dirección es una vista parcial muy tipográfica, pero el método EditorFor ofrece la posibilidad de agregar elementos de datos de vista adicionales fácilmente con un objeto anon.

En el ejemplo anterior no tuve que incluir el nombre de la plantilla "Dirección", ya que MVC buscaría una plantilla con el mismo nombre que el tipo de modelo.

También puede anular la plantilla de visualización de la misma manera.