2012-12-19 1 views
7

У меня есть метод действий, подобный приведенному ниже.DefaultModelBinder и набор унаследованных объектов

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

У меня есть модель со следующими классами, которую я хотел бы загрузить данные из данных ajax 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 обрабатывает структуру вложенных объектов, но не может разрешать различные подкласс.

Что было бы лучшим способом загрузить Список с соответствующими подклассами?

+0

Можете подробнее рассказать о том, что вы пытаетесь сделать здесь? Похоже, вы пытаетесь связать всю форму в viewmodel, а не только с ее значениями. Я могу понять, как создавать динамические формы на основе некоторых данных JSON, которые предоставляет бэкэнд, но я стараюсь понять, почему вы хотели бы снова предоставить бэкэнд вместо самой структуры вместо значений только тогда, когда пользователь заполняет форму. –

+0

Я не генерирую форму динамически. Я принимаю json, которые представляют структуру формы, которая будет сохранена позже в системе. – Thurein

ответ

1

Я просмотрел код реализации mvc DefaultModelBinder. При привязке модели DefaultModelBinder просматривайте свойства модели с помощью метода GetModelProperties(). Ниже показано, как DefaultModelBinder посмотреть свойства:

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

TypeDescriptorHelper.Get Пользуется ModelType, который является типом partent (в моем случае FormElement), так что свойства дочернего класса (TextBox, Combo) не получены ,

Вы можете переопределить метод и изменить поведение для получения определенного дочернего типа, как показано ниже.

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

 Смежные вопросы

  • Нет связанных вопросов^_^