2012-12-19 16 views
7

Tôi có một phương thức hành động như sau.DefaultModelBinder và tập hợp các đối tượng thừa kế

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

Tôi có mô hình với các lớp sau, mà tôi muốn tải dữ liệu từ dữ liệu 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; } 
} 

Đây là dữ liệu 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; 
       } 
      }); 

Mặc địnhModelBinder đang xử lý cấu trúc đối tượng lồng nhau nhưng không thể giải quyết các lớp con khác nhau.

Cách tốt nhất để tải Danh sách với các lớp con tương ứng là gì?

+0

Bạn có thể giải thích chi tiết hơn về những gì bạn đang cố gắng thực hiện ở đây không? Nó có vẻ như bạn đang cố gắng để ràng buộc toàn bộ hình thức vào viewmodel thay vì chỉ các giá trị nó mang. Tôi có thể thấy điểm tạo ra các biểu mẫu động dựa trên một số dữ liệu JSON mà backend cung cấp nhưng tôi cố gắng hiểu tại sao bạn lại muốn cung cấp phần phụ trợ thay vì các giá trị chỉ khi người dùng điền vào biểu mẫu. –

+0

Tôi không tạo biểu mẫu động. Tôi chấp nhận json đại diện cho cấu trúc của biểu mẫu sẽ được lưu sau này trong hệ thống. – Thurein

Trả lời

1

Tôi đã xem mã của triển khai DefaultModelBinder mvc. Khi ràng buộc một mô hình DefaultModelBinder tìm kiếm các thuộc tính của mô hình bằng cách sử dụng GetModelProperties(). Sau đây là cách DefaultModelBinder nhìn lên các thuộc tính:

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

TypeDescriptorHelper.Get là sử dụng ModelType đó là loại partent (trong trường hợp của tôi FormElement), vì vậy các thuộc tính của lớp con (TextBox, Combo) không được lấy ra .

Bạn có thể ghi đè phương thức và thay đổi hành vi để truy xuất loại con cụ thể như sau.

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