Oggetto complesso e modello legatore ASP.NET MVC

Ho una struttura di oggetti modello con una class Foo che contiene una Bar con un valore di stringa.

 public class Foo { public Bar Bar; } public class Bar { public string Value { get; set; } } 

E un modello di vista che usa quella struttura come questa

 public class HomeModel { public Foo Foo; } 

Ho quindi una forma in vista che in Razor assomiglia a qualcosa del genere.

  
@using (Html.BeginForm("Save", "Home", FormMethod.Post)) {
@Html.TextBoxFor(m => m.Foo.Bar.Value)
}

In html che diventa.

 

Finalmente il controller per gestire il post loos in questo modo

 [HttpPost] public ActionResult Save(Foo foo) { // Magic happends here return RedirectToAction("Index"); } 

Il mio problema è che Bar in Foo è null quando colpisce l’azione Save controller (viene creato Foo ma con un campo Bar null ).

Pensavo che il model binder in MVC sarebbe stato in grado di creare l’object Foo and the Bar e impostare la proprietà Value fintanto che appare come sopra. Cosa mi manca?

So anche che il mio modello di visualizzazione è un po ‘complicato e potrebbe essere più semplice, ma io per quello che sto cercando di fare mi aiuterebbe davvero se potessi usare la struttura dell’object più profonda. Gli esempi precedenti utilizzano ASP.NET 5.

In primo luogo, DefaultModelBinder non si DefaultModelBinder ai campi, quindi è necessario utilizzare le proprietà

 public class HomeModel { public Foo Foo { get; set; } } 

In secondo luogo, gli helper stanno generando controlli basati su HomeModel ma si sta postando su Foo . O cambiare il metodo POST in

 [HttpPost] public ActionResult Save(HomeModel model) 

oppure usa BindAttribute per specificare il Prefix (che sostanzialmente rimuove il valore del prefisso dai valori pubblicati – quindi Foo.Bar.Value diventa Bar.Value ai fini del binding)

 [HttpPost] public ActionResult Save([Bind(Prefix="Foo")]Foo model) 

Nota anche che non dovresti nominare il parametro method con lo stesso nome di una delle tue proprietà altrimenti il ​​binding fallirà e il tuo modello sarà nullo.

Ho appena scoperto un altro motivo per cui questo può accadere, ovvero se la tua proprietà è denominata Settings ! Si consideri il seguente modello di vista:

 public class SomeVM { public SomeSettings DSettings { get; set; } // named this way it will work public SomeSettings Settings { get; set; } // property named 'Settings' won't bind! public bool ResetToDefault { get; set; } } 

Nel codice, se si esegue il binding alla proprietà Settings , non riesce a eseguire il binding (non solo sul post ma anche sulla generazione del modulo). Se si rinominano le Settings su DSettings (ecc.), Esso funziona di nuovo all’improvviso.

Ho avuto lo stesso problema e dopo aver seguito i passaggi di @Stephen Muecke mi sono reso conto che il problema era causato dal fatto che i miei input erano disabilitati (li stavo disabilitando con JQuery su documenti pronti) come puoi vedere qui: Come invio l’input disabilitato in ASP.NET MVC? . Alla fine ho usato la sola lettura invece dell’attributo disabilitato e tutti i valori sono stati inviati con successo al controller.

Ho avuto lo stesso problema, ma una volta che ho creato un HIDDEN FIELD per la chiave esterna … tutto ha funzionato bene …

ESEMPIO DI FORMA:

 @using (Html.BeginForm("save", "meter", FormMethod.Post)) { @Html.AntiForgeryToken() @Html.ValidationSummary(true) @Html.HiddenFor(model => Model.Entity.Id) @Html.HiddenFor(model => Model.Entity.DifferentialMeter.MeterId) @Html.HiddenFor(model => Model.Entity.LinearMeter.MeterId) @Html.HiddenFor(model => Model.Entity.GatheringMeter.MeterId) ... all your awesome controls go here ... } 

ESEMPIO DI AZIONE:

 // POST: /Meter/Save [HttpPost] public ActionResult Save(Meter entity) { ... world-saving & amazing logic goes here ... } 

FOTOGRAFIE CARINE:
inserisci la descrizione dell'immagine qui