2012-12-19 1 views
7

다음과 같은 작업 방법이 있습니다.DefaultModelBinder 및 상속 된 객체의 컬렉션

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

은 내가 아약스 JSON 데이터에서 데이터를로드하고자하는 다음과 같은 클래스와 함께 모델이있다.

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

다음은 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는 중첩 된 개체 구조를 처리하지만 다른 하위 클래스는 확인할 수 없습니다.

각 하위 클래스로 List를로드하는 가장 좋은 방법은 무엇입니까?

+0

여기에서 수행하려는 작업에 대해 자세히 설명 할 수 있습니까? 전체 양식을 전달하는 값 대신 뷰 모델로 바인딩하려고하는 것처럼 보입니다. 백엔드가 제공하는 일부 JSON 데이터를 기반으로 양식을 동적으로 생성한다는 점을 알 수 있지만 사용자가 양식을 채울 때만 값 대신 구조 자체를 다시 제공하려는 이유를 이해하기 위해 애 쓰고 있습니다. –

+0

양식을 동적으로 생성하지 않습니다. 나중에 시스템에 저장 될 형식의 구조를 나타내는 json을 수락합니다. – Thurein

답변

1

mvc DefaultModelBinder 구현의 코드를 살펴 보았습니다. 모델을 바인딩 할 때 DefaultModelBinder는 GetModelProperties()를 사용하여 모델의 속성을 찾습니다. 검색되지 않습니다

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

TypeDescriptorHelper.Get이 (내 경우 FormElement 단위) partent 유형입니다 ModelType를 사용하여, 그래서 자식 클래스 (텍스트 상자, 콤보)의 속성 : 다음은 속성을 찾아 DefaultModelBinder 어떻게 .

아래와 같이 특정 하위 유형을 검색하기 위해 메소드를 재정의하고 동작을 변경할 수 있습니다.

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