Domanda

Ci sono alcune questioni connesse, ma non riesco a trovare una risposta che funziona.

Supponendo che ho le seguenti modelli:

public class EditorViewModel
{
  public Account Account {get;set;}
  public string SomeSimpleStuff {get;set;}
}

public class Account
{
  public string AccountName {get;set;}
  public int MorePrimitivesFollow {get;set;}
}

e una vista che si estende ViewPage<EditorViewModel> che esegue le seguenti:

<%= Html.TextBoxFor(model => model.Account.AccountName)%>
<%= Html.ValidationMessageFor(model => model.Account.AccountName)%>
<%= Html.TextBoxFor(model => model.SomeSimpleStuff )%>
<%= Html.ValidationMessageFor(model => model.SomeSimpleStuff )%>

e il mio aspetto del controller come:

[HttpPost]
public virtual ActionResult Edit(EditorViewModel account)
{ /*...*/ }

Come posso ottenere il DefaultModelBinder correttamente legano il mio EditorViewModel? Senza fare nulla di speciale, ho un'istanza vuota della mia EditorViewModel con null tutto o di default.

Il più vicino Sono venuto è chiamando manualmente UpdateModel:

[HttpPost]
public virtual ActionResult Edit(EditorViewModel account)
{
    account.Account = new Account();
    UpdateModel(account.Account, "Account");
    // this kills me:
    UpdateModel(account);

Questa aggiorna con successo il mio modello di proprietà Account, ma quando chiamo UpdateModel su account (per ottenere il resto delle proprietà pubbliche della mia EditorViewModel) ottengo il completamente inefficiente "Il modello di tipo ... non poteva essere aggiornato." Non v'è alcuna eccezione interna, quindi non riesco a capire cosa c'è che non va.

Cosa devo fare con questo?

È stato utile?

Soluzione

Il legante è sempre confuso perché vede che il parametro per il metodo di azione è denominato conto , e vede i campi del modulo in entrata denominati account.accountname , quindi è alla ricerca per una proprietà NomeAccount sul EditorViewModel.

È possibile risolvere questo problema rinominando il parametro a qualcos'altro che non lo fa conflitto con un campo di modulo in arrivo, oppure si può attaccare un [Bind (prefix = "")] attributo del parametro. Questo attributo dice "ignora il fatto che il parametro è denominato account , e far finta avevo dato un nome stringa vuota, invece." Poi il legante cercherà account.accountname al posto di account.account.accountname .

Modifica - ulteriori informazioni:

Quando il legante vede un parametro complesso denominato pippo , esamina la richiesta corrente per qualche cosa di nome * pippo. **. Così, se il parametro sono stati nominati pippo e il suo tipo aveva una proprietà denominata FirstName , il valore in entrata ci si aspetta di essere foo.FirstName = John , per esempio.

Tuttavia, se il legante non vede un pippo *. ** come parte della richiesta, sembra proprio per il * direttamente (senza il pippo prefisso). Quindi, fintanto che non c'era una pippo *. ** presente nella richiesta, si può inviare FirstName = John e il legante avrebbero capito questo in modo corretto. Ma se c'è qualche pippo *. ** come parte della richiesta, il FirstName = John valore non corrispondere alla proprietà FirstName.

Si può vedere ora come dare il parametro al metodo di azione lo stesso nome di una delle sue proprietà sarebbe buttare fuori questa logica.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top