c# - ASP.NET MVC 4 不会将 multipart/form-data 序列化为 C# 对象

标签 c# asp.net-mvc asp.net-mvc-4 serialization

我有一个奇怪的问题。我有多种具有基本 CRUD 操作的表单。下面是有问题的那个,不过基本上都是这样的:

@using (Html.BeginForm((string)ViewBag.FormAction, "Groups", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.HiddenFor(vm => vm.Groep.Id)
<table>
    <tbody>
        <tr>
            <td style="width: 150px;">@Html.LabelFor(x => x.Groep.Naam) @Html.Partial("RequiredFieldIndicator")</td>
            <td>@Html.EditorFor(model => model.Groep.Naam)</td>
        </tr>
        <tr>
            <td>@Html.LabelFor(x => x.Groep.PLCode) @Html.Partial("RequiredFieldIndicator")</td>
            <td>@Html.EditorFor(model => model.Groep.PLCode)</td>
        </tr>
    </tbody>
</table>
<br />
<br />
<div class="actionbuttons">
    @if (Model.FormEditModus == FormEditModus.Edit)
    {
        <button type="button" class="btn btn-default" onclick="location.href='@Url.Action("Detail", "Groups", new { id = @Model.Groep.Id })'">Terug</button>
    }
    @if (Model.FormEditModus == FormEditModus.Add)
    {
        <button type="button" class="btn btn-default" onclick="location.href='@Url.Action("Index", "Groups")'">Terug</button>
    }
    <button id="saveGroupButton" class="btn btn-default" type="submit">Opslaan</button>
    <button type="button" class="btn btn-default" onclick="location.href='@Url.Action("Index", "Groups")'">Annuleren</button>
</div>
}

我使用的 View 模型如下所示:

using Models;

namespace Admin.Models
{
public class GroupEditViewModel
{
    public Groep Groep { get; set; }

    //enum
    public FormEditModus FormEditModus { get; set; }
}


public class Groep : ModelKeyEntity
{
    [StringLength(200), Required]
    public string Naam { get; set; }

    [StringLength(20), Required]
    public string PLCode { get; set; }
}

public abstract class ModelKeyEntity 
{
    public int Id { get; set; }
}
}

一切都很基础。这就是为什么当发布表单时 MVC 上的操作总是收到空对象时,我感到很惊讶。雪上加霜的是,我的所有其他表单(具有相同的设置和几乎相同的 View 模型)都可以正常工作。但这是向 Controller 发送消息后的结果:

Groep is null

这是导致错误的 POST 信息:

------WebKitFormBoundaryUPb7u53aJYurdens
Content-Disposition: form-data; name="Groep.Id"

20
------WebKitFormBoundaryUPb7u53aJYurdens
Content-Disposition: form-data; name="Groep"

Models.Groep
------WebKitFormBoundaryUPb7u53aJYurdens
Content-Disposition: form-data; name="Groep.Naam"

Polantx
------WebKitFormBoundaryUPb7u53aJYurdens
Content-Disposition: form-data; name="Groep.PLCode"

PL2000x
------WebKitFormBoundaryUPb7u53aJYurdens--

一切都是(我认为)应该是的。唯一的问题是 MVC 拒绝将表单数据序列化为对象。

不用说,我在这一点上很无能。其他人有线索吗?

最佳答案

默认的模型绑定(bind)器不能很好地处理嵌套的复杂对象。我通过编写一个简单的 jQuery 扩展来序列化表单数据然后在自定义模型 Binder 中使用 Json.Net 来解决这个问题。

这感觉真的很糟糕,但效果很好。

这是 jQuery:

   $.fn.serializeToJson = function () {
    var $form = $(this[0]);
    var items = $form.serializeArray();
    var returnObj = {};
    var nestedObjectNames = [];

    $.each(items, function (i, item) {
        //Split nested objects and assign properties
        //You may want to make this recursive - currently only works one step deep, but that's all I need
        if (item.name.contains('.')) {
            var nameArray = item.name.split('.');
            if (nestedObjectNames.indexOf(nameArray[0]) < 0) {
                nestedObjectNames.push(nameArray[0]);
            }
            var tempObj = returnObj[nestedObjectNames[nestedObjectNames.indexOf(nameArray[0])]] || {};
            if (!tempObj[nameArray[1]]) {
                tempObj[nameArray[1]] = item.value;
            }
            returnObj[nestedObjectNames[nestedObjectNames.indexOf(nameArray[0])]] = tempObj;
        } else if (!returnObj[item.name]) {
            returnObj[item.name] = item.value;
        }
    });

    return returnObj;
};

调用它:

var data = JSON.stringify($('form').serializeToJson());
$.post(url, data).done(...

然后是 Binder :

using System.Web.Mvc;
using Newtonsoft.Json;

namespace Namespace.Web.Core.Binders
{
    public class JsonBinder<T> : IModelBinder
    {
       public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var jsonString = controllerContext.RequestContext.HttpContext.Request.Params[0];
            return JsonConvert.DeserializeObject<T>(jsonString);
        }
    }
}

并在使用中:

public ActionResult WhateverAction([ModelBinder(typeof(JsonBinder<CustomViewModel>))]CustomViewModel viewModel)

编辑:忘记提及,您可能需要对数据进行字符串化。更新如上。

关于c# - ASP.NET MVC 4 不会将 multipart/form-data 序列化为 C# 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23828829/

相关文章:

c# - 如何创建类的实例并注入(inject)服务?

asp.net-mvc - 如何在一个 View 中使用两个 IEnumerable 模型

c# - 动态加载 DbSet 到 DbContext

c# - Sendgrid X-SMTP-API 在使用 EnableTemplateEngine 时返回错误

c# - Microsoft.Graph.AttendeeType 未正确枚举

c# - asp.net mvc开发者的Java框架推荐

c# - 不正确的代码契约(Contract)警告

c# - MVC、 View 和 System.Data.Entity

c# - Asp Web Api 异步操作 - 404 错误

asp.net-mvc - debug 加载当前 View 而不是在routeconfig Mvc 4 中指定的 View