2012-12-19 12 views
7

Ho un metodo di azione come questo di seguito.DefaultModelBinder e raccolta di oggetti ereditati

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create(Form newForm) 
{ 
    ... 
} 

Ho un modello con le seguenti classi, che mi piacerebbe caricare i dati dai dati JSON Ajax.

public class Form 
{ 
    public string title { get; set; } 

    public List<FormElement> Controls { get; set; } 

} 

public class FormElement 
{ 
    public string ControlType { get; set; } 

    public string FieldSize { get; set; } 
} 

public class TextBox : FormElement 
{ 
    public string DefaultValue { get; set; } 
} 

public class Combo : FormElement 
{ 
    public string SelectedValue { get; set; } 
} 

Ecco i dati JSON.

{ "title": "FORM1", 
"Controls": 
[ 
{ "ControlType": "TextBox", "FieldSize": "Small" ,"DefaultValue":"test"}, 
{ "ControlType": "Combo", "FieldSize": "Large" , "SelectedValue":"Option1" } 
] 
} 


$.ajax({ 
       url: '@Url.Action("Create", "Form")', 
       type: 'POST', 
       dataType: 'json', 
       data: newForm, 
       contentType: 'application/json; charset=utf-8', 
       success: function (data) { 
        var msg = data.Message; 
       } 
      }); 

DefaultModelBinder gestisce la struttura dell'oggetto nidificata ma non può risolvere i differenti sottoclassi.

Quale sarebbe il modo migliore per caricare Elenco con le rispettive sottoclassi?

+0

Puoi spiegare in dettaglio cosa stai cercando di realizzare qui? Sembra che tu stia cercando di associare l'intero modulo al viewmodel invece dei soli valori che contiene. Riesco a vedere il punto nel generare dinamicamente le forme basandosi su alcuni dati JSON forniti dal backend, ma faccio fatica a capire perché vorresti fornire di nuovo il backend alla struttura stessa invece dei valori solo quando un utente compila il modulo. –

+0

Non sto generando il modulo in modo dinamico. Sto accettando il json che rappresenta la struttura del modulo che verrà salvato successivamente nel sistema. – Thurein

risposta

1

Ho esaminato il codice dell'implementazione DefaultModelBinder di mvc. Quando si associa un modello DefaultModelBinder, cercare le proprietà del modello utilizzando GetModelProperties(). Quello che segue è il modo DefaultModelBinder cercare le proprietà:

protected virtual ICustomTypeDescriptor GetTypeDescriptor(ControllerContext controllerContext, ModelBindingContext bindingContext) { 
      return TypeDescriptorHelper.Get(bindingContext.ModelType); 
     } 

TypeDescriptorHelper.Get sta usando ModelType che è il tipo partent (nel mio caso FormElement), in modo che le proprietà della classe figlia (TextBox, Combo) non vengono recuperati .

È possibile sovrascrivere il metodo e modificare il comportamento per recuperare il tipo di figlio specifico come indicato di seguito.

protected override System.ComponentModel.PropertyDescriptorCollection GetModelProperties(ControllerContext controllerContext, ModelBindingContext bindingContext) 
{ 
    Type realType = bindingContext.Model.GetType(); 
    return new AssociatedMetadataTypeTypeDescriptionProvider(realType).GetTypeDescriptor(realType).GetProperties(); 
} 


protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) 
     { 
      ValueProviderResult result; 
      result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".ControlType"); 

      if (result == null) 
       return null; 

      if (result.AttemptedValue.Equals("TextBox")) 
       return base.CreateModel(controllerContext, 
         bindingContext, 
         typeof(TextBox)); 
      else if (result.AttemptedValue.Equals("Combo")) 
       return base.CreateModel(controllerContext, 
         bindingContext, 
         typeof(Combo)); 
      return null; 
     } 
Problemi correlati