ottenere i valori da un object complesso nidificato passato a una vista parziale

Ho un ViewModel che ha un object complesso come uno dei suoi membri. L’object complesso ha 4 proprietà (tutte le stringhe). Sto cercando di creare una vista parziale riutilizzabile in cui posso passare l’object complesso e fargli generare l’html con helper html per le sue proprietà. Funziona tutto alla grande. Tuttavia, quando invio il modulo, il raccoglitore modello non sta mappando i valori sul membro ViewModel in modo da non ottenere nulla sul lato server. Come posso leggere i valori che un utente digita negli helper html per l’object complesso.

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; } .... } 

controllore

 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); } } 

vista

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

Vista parziale

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

come posso associare questi dati all’invio del modulo in modo che il modello principale contenga i dati inseriti nel modulo Web dalla vista parziale?

Grazie

EDIT: ho capito che ho bisogno di anteporre “ComplexModel”. a tutti i nomi del mio controllo nella vista parziale (caselle di testo) in modo che si associ all’object nidificato, ma non posso passare il tipo ViewModel alla vista parziale per ottenere quel livello in più perché deve essere generico per accettare diversi ViewModel tipi. Potrei semplicemente riscrivere l’attributo name con javascript, ma mi sembra troppo ghetto. In quale altro modo posso fare questo?

EDIT 2: Posso impostare staticamente l’attributo name con new {Name = “ComplexModel.Name”} quindi penso di essere in affari a meno che qualcuno non abbia un metodo migliore?

È ansible passare il prefisso all’utilizzo parziale

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

che perpendicherà il prefisso a te controlla l’attributo name modo che diventi e si leghi correttamente a typeof MyViewModel sul post back

modificare

Per renderlo un po ‘più semplice, puoi racchiuderlo in 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); } 

e usarlo come

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

Puoi provare a passare ViewModel al parziale.

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

modificare

È ansible creare un modello base e inserire il modello complesso e trasferire il modello basato sul modello parziale.

 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; } ... } 

Allora il tuo parziale sarà come di seguito:

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

Se questa non è una soluzione accettabile, potrebbe essere necessario pensare in termini di sovrascrittura del raccoglitore del modello. Puoi leggere a riguardo qui .

Mi sono imbattuto nella stessa situazione e con l’aiuto di questi post informativi ho modificato il mio codice parziale in modo da avere il prefisso generato in elementi di input generati dalla vista parziale

Ho usato l’helper Html.partial dando il nome partialview e l’object di ModelType e un’istanza dell’object ViewDataDictionary con Html Field Prefix al costruttore di Html.partial.

Ciò si traduce in richiesta GET di “xyz url” di “Vista principale” e rendering parziale vista all’interno di esso con elementi di input generati con prefisso es. Nome precedente = “Titolo” diventa Nome = “MySubType.Title” nel rispettivo elemento HTML e lo stesso per resto degli elementi di input del modulo.

Il problema si è verificato quando si effettua la richiesta POST a “xyz url”, aspettandosi che il modulo che viene compilato venga salvato nel mio database. Ma MVC Modelbinder non ha vincolato i dati del modello POSTed con i valori dei moduli compilati e anche ModelState è stato perso. Anche il modello in viewdata stava arrivando a zero.

Alla fine ho provato ad aggiornare i dati del modello in forma postata usando il metodo TryUppdateModel che prende l’istanza del modello e il prefisso html che è stato passato in precedenza alla vista parziale, e può vedere ora che il modello è associato con valori e lo stato del modello è presente.

Per favore fatemi sapere se questo approccio è buono o leggermente diversificato!