我有一个奇怪的问题。我有多种具有基本 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 发送消息后的结果:
这是导致错误的 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/