在ASP.NET MVC 5中,如何从FormCollection反序列化复杂对象?

时间:2019-04-12 17:19:16

标签: c# asp.net-mvc asp.net-mvc-5

ASP.NET MVC 5中是否存在可访问的工具,以从[HttpPost]操作中获取FormCollection参数并将其反序列化为给定类型?喜欢MyModelType myModel = SOMEHOWDSERIALIZE<MyModelType>(formCollection);

我们使用常规的EditorFor绑定在ASP.NET MVC 5中使用了一个复杂的对象,帖子 用于 看起来像这样:< / p>

[HttpPost]
public ActionResult MyModelAction(MyModelV1 myModel)
{
    // .. process the model here
}

现在,我们拥有该模型的新版本,并且 不会创建新的路径/ URL 以发布新的模型版本有效负载。该模型的属性具有足够的元数据供我们推断其反序列化类型,因此我们可以使用表单字段中的元数据来解密要反序列化和执行的模型类型。所以现在看起来像这样:

[HttpPost]
public ActionResult MyModelAction(FormCollection parameters)
{
    switch (parameters["OurVersionDisambiguator"])
    {
        case "V1":
            var myModel_V1 = SOMEHOW_DESERIALIZE<MyModel_V1>(parameters);
            return MyModelAction(myModel_V1);
        case "V2":
            var myModel_V2 = SOMEHOW_DESERIALIZE<MyModel_V2>(parameters);
            return MyModelAction(myModel_V2);
        default: throw new NotImplementedException();
    }
}

[NonAction]
public ActionResult MyModelAction(MyModelV1 myModelV1) 
{
    // process the model
}

[NonAction]
public ActionResult MyModelAction(MyModelV2 myModelV2) 
{
    // process the model
}

在上面的示例中,我推断将创建类似于以下方法的内容,但不确定如何处理...

T SOMEHOW_DESERIALIZE<T>(FormCollection parameters)

我知道我可以使用Activator和Reflection并手动“手工”输入反序列化,但是由于ASP.NET MVC通常在不使用FormCollection时自动为我们完成反序列化,因此肯定有这样的工具我们可以单线调用吗?

请注意,在上述示例中,处理过程必须继续能够访问Request上下文,因为在同一请求中可能有要处理的文件上传流。

1 个答案:

答案 0 :(得分:1)

由于我一直在寻找一种简单的方法来将FormCollection绑定到运行时类型已知的模型,因此拥有自定义模型绑定器并不是解决方案。幸运的是,我正在寻找的内置功能是TryUpdateModel(..)

[HttpPost]
public ActionResult MyModelAction(FormCollection parameters)
{
    switch (parameters["OurVersionDisambiguator"])
    {
        case "V1":
            var myModel_V1 = new MyModel_V1();
            var hasModelStateError /* ignoring */ =
                TryUpdateModel(myModel_V1, parameters.ToValueProvider());
            return MyModelAction(myModel_V1);
        case "V2":
            var myModel_V2 = new MyModel_V2();
            var hasModelStateError /* ignoring */ =
                TryUpdateModel(myModel_V2, parameters.ToValueProvider());
            return MyModelAction(myModel_V2);
        default: throw new NotImplementedException();
    }
}

[NonAction]
public ActionResult MyModelAction(MyModelV1 myModelV1) 
{
    // process the model
}

[NonAction]
public ActionResult MyModelAction(MyModelV2 myModelV2) 
{
    // process the model
}