2012-12-19 12 views
7

Aşağıda benzer bir işlem yöntemim var.DefaultModelBinder ve devralınan nesnelerin toplanması

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

Ajax JSON verilerinden veri yüklemek istediğim aşağıdaki sınıflara sahip bir modelim var.

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

İşte JSON verisi.

{ "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, iç içe geçmiş nesne yapısını ele alıyor ancak farklı alt sınıfları çözemiyor.

Listeyi ilgili alt sınıflarla yüklemenin en iyi yolu ne olurdu?

+0

Burada neyi başarmaya çalıştığınızı daha ayrıntılı olarak açıklayabilir misiniz? Tüm formu, taşıdığı değerler yerine, görünüm modeline bağlamaya çalışıyorsunuz gibi görünüyor. Arka uçların sağladığı bazı JSON verilerine dayanarak dinamik olarak formları oluşturmanın noktasını görebiliyorum ancak neden sadece bir kullanıcı formda dolduğunda değerlerin yerine yapıyı yeniden sunmak istediğimi anlamak için uğraşıyorum. –

+0

Formu dinamik olarak oluşturmuyorum. Daha sonra sistemde saklanacak olan formun yapısını temsil eden jsonu kabul ediyorum. – Thurein

cevap

1

mvc DefaultModelBinder uygulamasının kodunu inceledim. Bir model DefaultModelBinder bağlandığında GetModelProperties() kullanarak modelin özelliklerini arayın. geri alınmazsa

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

TypeDescriptorHelper.Get (benim durumumda FormElement olarak) partent türüdür ModelType kullanarak, bu nedenle çocuk sınıfı (TextBox, Combo) özelliklerini: Aşağıdaki özelliklere bakmak DefaultModelBinder nasıl .

Yöntemi geçersiz kılabilir ve belirli alt türlerini aşağıdaki gibi almak için davranışı değiştirebilirsiniz.

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