2009-04-03 15 views
7

Sto provando a scrivere un raccoglitore modello personalizzato ma sto riscontrando grandi difficoltà nel tentativo di capire come associare oggetti compositi complessi.Raccoglitore modello personalizzato per oggetti compositi complessi HELP

Questa è la classe che sto cercando di legarsi a:

public class Fund 
{ 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public List<FundAllocation> FundAllocations { get; set; } 
} 

e questo è come il mio tentativo di scrivere il legante personalizzato appare come:

public class FundModelBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     throw new NotImplementedException(); 
    } 

    public object GetValue(ControllerContext controllerContext, string modelName, Type modelType, ModelStateDictionary modelState) 
    { 
     var fund = new Fund(); 

     fund.Id = int.Parse(controllerContext.HttpContext.Request.Form["Id"]); 
     fund.Name = controllerContext.HttpContext.Request.Form["Name"]; 

     //i don't know how to bind to the list property :(
     fund.FundItems[0].Catalogue.Id = controllerContext.HttpContext.Request.Form["FundItem.Catalogue.Id"]; 
     return fund; 
    } 
} 

Tutte le idee

grazie Tony

+0

Ho appena inserito una domanda e alla fine ho trovato una soluzione a questo stesso tipo di problema. Per chi fosse interessato, si consiglia di controllare il seguente link: [http://stackoverflow.com/questions/1077481/how-do-i-pass-a-dictionary-as-a-parameter-to-an-actionresult -Metodo-da-jquery-a] (http://stackoverflow.com/questions/1077481/how-do-i-pass-a-dictionary-as-a-parameter-to-an-actionresult-method-from- jquery-a) –

risposta

3

Ho speso troppo per questo esatto s cosa ame ultimamente!

Senza visualizzare il modulo HTML, suppongo che stia semplicemente restituendo i risultati della selezione da un elenco a selezione multipla o qualcosa del genere? In questo caso, il tuo modulo restituisce semplicemente un numero di numeri interi anziché restituire l'oggetto idratato FundAllocations. Se vuoi farlo allora, nel tuo ModelBinder personalizzato, avrai bisogno di fare la tua ricerca e idratare l'oggetto tu stesso.

Qualcosa di simile:

fund.FundAllocations = 
     repository.Where(f => 
     controllerContext.HttpContext.Request.Form["FundItem.Catalogue.Id"].Contains(f.Id.ToString()); 

Naturalmente, il mio LINQ è solo per esempio e, ovviamente, si può recuperare i dati in ogni caso che si desidera. Per inciso, e so che non risponde alla tua domanda, ma dopo aver fatto molti errori ho deciso che per oggetti complessi, è meglio usare un ViewModel e avere il ModelBinder predefinito per legarlo e poi, se necessario, idratare il modello che rappresenta la mia entità. Ci sono una serie di problemi in cui mi sono imbattuto e che hanno reso questa la scelta migliore, non ti annoierò con loro ora, ma sono felice di estrapolarti se lo desideri.

L'ultima Herding Code podcast è una grande discussione di questo come lo sono K Scott Allen's Putting the M in MVC blog posts.

8

Avete davvero bisogno di implementare un ModelBinder personalizzato qui? Il legante di default può fare ciò che è necessario (come si può compilare collezioni e oggetti complessi):

permette di dire la vostra azione di controllo è simile al seguente:

public ActionResult SomeAction(Fund fund) 
{ 
    //do some stuff 
    return View(); 
} 

E HTML contiene questo:

<input type="text" name="fund.Id" value="1" /> 
<input type="text" name="fund.Name" value="SomeName" /> 

<input type="text" name="fund.FundAllocations.Index" value="0" /> 
<input type="text" name="fund.FundAllocations[0].SomeProperty" value="abc" /> 

<input type="text" name="fund.FundAllocations.Index" value="1" /> 
<input type="text" name="fund.FundAllocations[1].SomeProperty" value="xyz" /> 

Il raccoglitore modello predefinito dovrebbe inizializzare l'oggetto del fondo con 2 voci nell'elenco delle raccolte fondi (non so quale sia la classe FundAllocations, quindi ho creato una singola proprietà "SomeProperty"). Assicurati di includere quegli elementi "fund.FundAllocations.Index" (che il raccoglitore predefinito considera per il proprio uso), che mi hanno preso quando ho provato a farlo funzionare).

+0

JonoW: hai un link per una buona documentazione per il raccoglitore modello standard, o hai appena guardato la fonte? –

+0

Will, scusa, non ho un link a nessuna documentazione ufficiale, stavo davvero seguendo il consiglio di Phil Haack sul suo blog, perché avevo un problema simile - http://haacked.com/archive/2008/10 /23/model-binding-to-a-list.aspx. Potrebbe esserci un modo migliore per farlo in 1.0, non sono sicuro ... – JonoW

+0

È corretto, non è necessario un modello personalizzato. Puoi farlo manipolando il campo del nome come mostrato sopra. – MedicineMan

Problemi correlati