MVC UpdateModel和子类与基类

Tr1*_*tan 4 asp.net-mvc asp.net-3.5 updatemodel subclassing

我正在寻找将UpdateModel方法用于在运行时检索的Sub Class,如果有人可以了解我是否正在对其进行总体哈希和/或我是否正在尝试做是可能的.

我正在使用通用操作来控制一堆部分视图的验证; 我试图摆脱每个局部视图的特定动作.

每个局部视图都有一个从基本模型派生的唯一模型:

public class ModelA : ModelBase{
     [Required]
     public string SomeStringProperty{get;set;}
...
}
public class ModelB : ModelBase{
     [Required]
     public DateTime? SomeDateProperty{get;set;}
...
}
public class ModelBase{
     public Guid InstanceId{get;set;}
}
Run Code Online (Sandbox Code Playgroud)

我正在使用Action上的FormCollection来获取提交的表单元素及其值,这包括View应该用于验证其请求的模型类型.忽略这个例子的安全含义,我知道它们,这是一个内部唯一的概念证明

    [HttpPost]
    public ActionResult ChangeCaseState(int id, FormCollection formCollection)
    {
        Guid instanceId = new Guid(formCollection["instanceId"]);
        string modelType = formCollection["modelType"];
        //Return a specific Model class based on the event/modelType
        var args = GetStateModelClass(modelType, instanceId);

        try
        {
            UpdateModel(args);
            if(Model.IsValid){
             ...
        }
        catch (Exception)
        {
            return View("~/Views/Shared/StateForms/" + modelType + ".ascx", args);
        }...
Run Code Online (Sandbox Code Playgroud)

这里是我用来返回基于传递给控制器​​的modelType的Sub Class的代码.

private static ModelBase StateModelClassFactory(string stateModelTypeName, Guid instanceId)
        {
            switch (stateModelTypeName)
            {
                case "modelTypeA":
                    return new ModelA(workflowInstanceId);
                case "modelTypeB":
                    return new ModelB(workflowInstanceId);
    ...
    }
Run Code Online (Sandbox Code Playgroud)

因为StateModelClassFactory方法的返回类型属于基类,即使我实际上返回了一个Sub类,UpdateModel方法使用的Model Binder也仅绑定Base Class中的值.

关于如何解决这个问题的任何想法?

更新:

我创建了一个Customer Model Binder:

public class CustomModelBinder : DefaultModelBinder
    {
      public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
Run Code Online (Sandbox Code Playgroud)

并将新的Model Binder分配给正确的Base Class,以了解更多内容:

ModelBinders.Binders.Add(typeof(ModelBase), new CaseController.CustomModelBinder());
Run Code Online (Sandbox Code Playgroud)

当我调试模型绑定器并检查bindingContext时,Model属性表示正确的Sub Class,但ModelType属性是Base Class的属性.我应该考虑在BindModel方法中更改ModelType吗?如果有任何关于如何执行此操作的指针,那么ModelType上的setter似乎已经变得多余了.我还注意到Sub Class中的SomeDateProperty是在PropertyMetadata属性中的行为....看起来如此接近于我想要的行为.

DMa*_*yer 5

我刚刚遇到这个特殊的问题,发现一个更好的通用方法就是将模型dynamic转换为UpdateModel:

[HttpPost]
public ActionResult ChangeCaseState(int id, FormCollection formCollection)
{
    ...try
    {
        UpdateModel((dynamic)args);//!!notice cast to dynamic here
        if(Model.IsValid){
         ...
    }
    catch...
Run Code Online (Sandbox Code Playgroud)

这似乎设置了我的类型的所有可用属性,无论我的变量是否与基类型相关.

CodePlex中有针对此问题提交的工作项:http://aspnet.codeplex.com/workitem/8277? ProjectName = aspnet