obtener los valores de un objeto complejo nested que se pasa a una vista parcial

Tengo un ViewModel que tiene un objeto complejo como uno de sus miembros. El objeto complejo tiene 4 propiedades (todas las cadenas). Intento crear una vista parcial reutilizable donde pueda pasar el objeto complejo y hacer que genere el html con html helpers para sus propiedades. Todo está funcionando bien. Sin embargo, cuando envío el formulario, la carpeta de modelo no correlaciona los valores con el miembro de ViewModel, por lo que no recibo nada en el servidor. ¿Cómo puedo leer los valores que un usuario escribe en los helpers html para el objeto complejo?

ViewModel

public class MyViewModel { public string SomeProperty { get; set; } public MyComplexModel ComplexModel { get; set; } } 

MyComplexModel

 public class MyComplexModel { public int id { get; set; } public string Name { get; set; } public string Address { get; set; } .... } 

Controlador

 public class MyController : Controller { public ActionResult Index() { MyViewModel model = new MyViewModel(); model.ComplexModel = new MyComplexModel(); model.ComplexModel.id = 15; return View(model); } [HttpPost] public ActionResult Index(MyViewModel model) { // model here never has my nested model populated in the partial view return View(model); } } 

Ver

 @using(Html.BeginForm("Index", "MyController", FormMethod.Post)) { .... @Html.Partial("MyPartialView", Model.ComplexModel) } 

Vista parcial

 @model my.path.to.namespace.MyComplexModel @Html.TextBoxFor(m => m.Name) ... 

¿Cómo puedo vincular estos datos en el envío de formularios para que el modelo principal contenga los datos ingresados ​​en el formulario web desde la vista parcial?

Gracias

EDITAR: he descubierto que tengo que anteponer “ComplexModel”. a todos los nombres de mi control en la vista parcial (cuadros de texto) para que se correlacione con el objeto nested, pero no puedo pasar el tipo de modelo de vista a la vista parcial para obtener esa capa adicional porque debe ser genérico para aceptar varios ViewModel tipos. Podría reescribir el atributo de nombre con javascript, pero eso me parece demasiado gueto. ¿De qué otra manera puedo hacer esto?

EDIT 2: Puedo establecer estáticamente el atributo de nombre con el nuevo {Name = “ComplexModel.Name”}, así que creo que estoy en el negocio a menos que alguien tenga un método mejor.

Puede pasar el prefijo al uso parcial

 @Html.Partial("MyPartialView", Model.ComplexModel, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "ComplexModel" }}) 

que perpendirá el prefijo a usted controla el atributo de name para que se convierta en y se vincule correctamente al tipo MyViewModel en la publicación posterior

Editar

Para que sea un poco más fácil, puede encapsular esto en un helper html

 public static MvcHtmlString PartialFor(this HtmlHelper helper, Expression> expression, string partialViewName) { string name = ExpressionHelper.GetExpressionText(expression); object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model; var viewData = new ViewDataDictionary(helper.ViewData) { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = name } }; return helper.Partial(partialViewName, model, viewData); } 

y usarlo como

 @Html.PartialFor(m => m.ComplexModel, "MyPartialView") 

Puede intentar pasar ViewModel al parcial.

 @model my.path.to.namespace.MyViewModel @Html.TextBoxFor(m => m.ComplexModel.Name) 

Editar

Puede crear un modelo base e insertar el modelo complejo allí y pasar el modelo basado en el parcial.

 public class MyViewModel :BaseModel { public string SomeProperty { get; set; } } public class MyViewModel2 :BaseModel { public string SomeProperty2 { get; set; } } public class BaseModel { public MyComplexModel ComplexModel { get; set; } } public class MyComplexModel { public int id { get; set; } public string Name { get; set; } ... } 

Entonces su parcial será como a continuación:

 @model my.path.to.namespace.BaseModel @Html.TextBoxFor(m => m.ComplexModel.Name) 

Si esta no es una solución aceptable, puede que tenga que pensar en términos de anular el encuadernador modelo. Puedes leer sobre eso aquí .

Me encontré con la misma situación y con la ayuda de tales mensajes informativos cambié mi código parcial para tener el prefijo generado en elementos de entrada generados por vista parcial

He usado Html.partial helper dando el nombre de partialview y el objeto de ModelType y una instancia del objeto ViewDataDictionary con Html Field Prefix al constructor de Html.partial.

Esto da como resultado una solicitud GET de “xyz url” de “Vista principal” y una vista parcial en su interior con elementos de entrada generados con prefijo, por ejemplo, Nombre anterior = “Título” ahora se convierte en Name = “MySubType.Title” en el elemento HTML respectivo y lo mismo para rest de los elementos de entrada de formulario.

El problema ocurrió cuando la solicitud POST se realiza en “xyz url”, esperando que el formulario que se llena se guarde en mi base de datos. Pero el MVC Modelbinder no enlazó mis datos de modelo POSTed con los valores de formulario completados y también se perdió también ModelState. El modelo en viewdata también venía a nulo.

Finalmente traté de actualizar los datos del modelo en forma publicada usando el método TryUppdateModel que toma la instancia del modelo y el prefijo html que se pasó anteriormente a la vista parcial, y puede ver ahora que el modelo está vinculado con los valores y el estado del modelo también está presente.

Por favor, avíseme si este enfoque es bueno o poco diversificado.