C# 如何在Asp.NETMVC4中绑定多态模型中的复杂属性?

C# 如何在Asp.NETMVC4中绑定多态模型中的复杂属性?,c#,model-view-controller,model-binding,custom-model-binder,C#,Model View Controller,Model Binding,Custom Model Binder,我需要基于派生类型创建一个动态输入表单,但在传递到控制器的POST方法时,无法正确绑定复杂属性。其他属性绑定良好。以下是我所拥有的一个人为的例子: 型号 public abstract class ModelBase {} public class ModelDerivedA : ModelBase { public string SomeProperty { get; set; } public SomeType MySomeType{ get;

我需要基于派生类型创建一个动态输入表单,但在传递到控制器的POST方法时,无法正确绑定复杂属性。其他属性绑定良好。以下是我所拥有的一个人为的例子:

型号

public abstract class ModelBase {}

public class ModelDerivedA : ModelBase
{       
    public string SomeProperty { get; set; }       
    public SomeType MySomeType{ get; set; }

    public ModelDerivedA()
    {
        MySomeType = new SomeType();
    }
}

public class SomeType 
{             
    public string SomeTypeStringA { get; set; }
    public string SomeTypeStringB { get; set; }         
}
自定义模型活页夹

[HttpPost]
public ActionResult    GetDynamicForm([ModelBinder(typeof(BaseViewModelBinder))] ModelBase model)
{
   // model HAS values for SomeProperty 
   // model has NO values for MySomeType
}
活页夹基于以下答案:

控制器

[HttpPost]
public ActionResult    GetDynamicForm([ModelBinder(typeof(BaseViewModelBinder))] ModelBase model)
{
   // model HAS values for SomeProperty 
   // model has NO values for MySomeType
}
查看摘录

@Html.Hidden("ModelType", Model.GetType())
@Html.Test(Model);
JavaScript

@Html.Hidden("ModelType", Model.GetType())
@Html.Test(Model);
表单是使用
$发布的。ajax
使用
数据:$(this).serialize()
,如果我调试,它将显示正确填充的表单数据

所有属性都填充在模型中,不包括
SomeType
的属性。我需要做哪些更改才能填充它们


谢谢

尝试将默认构造函数添加到您的
ModelDerivedA
以初始化
MySomeType

public class ModelDerivedA : ModelBase
{
    public ModelDerivedA()
    {
        MySomeType = new SomeType();
    }
}

未填充值,因为您正在创建以下类型的新实例:

var model = Activator.CreateInstance(type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
return model;
并返回不正确的相同模型

做下面这样的事情

ValueProviderResult valueResult;
bindingContext.ModelState.SetModelValue("ModelType", valueResult);       
return valueResult;
下面是关于modelBinder的非常好的讨论


我通过以下方式解决了眼前的问题:

  • 获取
    FormvalueProvider
    的实例(以访问已发布的内容)
  • 递归地遍历我的模型,并将每个属性值设置为
    FormValueProvider中的匹配值

    private FormValueProvider vp;
    
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var typeValue = bindingContext.ValueProvider.GetValue("ModelType");
    
        var type = Type.GetType(
            (string)typeValue.ConvertTo(typeof(string)),
            true
        );
        if (!typeof(ModelBase).IsAssignableFrom(type))
        {
            throw new InvalidOperationException("Bad Type");
        }
    
        var model = Activator.CreateInstance(type);
    
        vp = new FormValueProvider(controllerContext);
    
        bindingContext.ValueProvider = vp;
        SetModelPropertValues(model);
    
        return model;        
    }
    
  • 和递归,基于这个答案打印嵌套对象中的属性

        private void SetModelPropertValues(object obj)
        {
            Type objType = obj.GetType();
            PropertyInfo[] properties = objType.GetProperties();
            foreach (PropertyInfo property in properties)
            {
                object propValue = property.GetValue(obj, null);
                var elems = propValue as IList;
                if (elems != null)
                {
                    foreach (var item in elems)
                    {
                        this.SetModelPropertValues(item);
                    }
                }
                else
                {                   
                    if (property.PropertyType.Assembly == objType.Assembly)
                    {                        
                        this.SetModelPropertValues(propValue);
                    }
                    else
                    {
                      property.SetValue(obj, this.vp.GetValue(property.Name).AttemptedValue, null);
                    }
                }
            }
        }
    
    任何使用它的人都可能需要使它更加健壮,以满足他们的需求

    作为解决这类问题的一般方法,听到这种方法有什么缺点,我会非常感兴趣


    然而,我希望这篇文章能在某些情况下有所帮助。

    你的意思是什么,请解释一下?这个构造函数应该创建一个
    SomeType
    的实例。但是它会通过填充表单字段来解决问题吗?@Max,谢谢,在我的示例中这是一个问题,修复后它不会修复绑定问题。@davy它不会修复绑定问题。谢谢@Jenish,但是不是所有的属性都是空的吗(不仅仅是复杂的财产)?是的,我不能让它工作,但我今天没有花很多时间在它上。