asp.net-mvc - 如何对 MVC 3 应用程序进行表单 POST 并获取反序列化类?

标签 asp.net-mvc post knockout.js object-serialization

我有以下表格:

<form id="MakeDocumentForm" name="MakeDocumentForm" 
      action="Document/GetWordDocument" method="post" 
      enctype="application/json">

    <button type="submit" style="float:right;">Make Word Document</button> 
    <textarea id="hiddenJson" 
              name="hiddenJson" 
              data-bind="text: ko.toJSON(viewModel.selectedDocument)" 
              rows="5" cols="100" 
              style="visibility:hidden;" >
    </textarea>

</form>

data-bind 属性是 knockoutjs - 但这并不重要,textarea 正确包含作为序列化对象的 JSON。

[HttpPost]
public void GetWordDocument(DocumentModel hiddenJson)
{
   //hiddenJson is not a correctly populated instance of my DocumentModel class
   //any MVC experts know what I am doing wrong?
}

现在,如何将表单 POST 到 MVC 3 应用程序并获取反序列化的类?

最佳答案

如果您通过 AJAX 发布它,并将内容类型设置为 JSON,那么 MVC 3 将能够在您的 Controller 操作中正确绑定(bind)它。

$.ajax({
    url: location.href, 
    type: "POST",
    data: ko.toJSON(viewModel),
    datatype: "json",
    contentType: "application/json charset=utf-8",
    success: function (data) { alert("success"); }, 
    error: function (data) { alert("error"); }
});

但是,如果像在您的示例中一样,您想要执行包含 JSON 的普通表单发布,那么您需要做更多的工作,因为 MVC3 不会自动将其绑定(bind)到您的模型,因为内容类型将是应用程序/x-www-form-urlencoded。

史蒂夫·桑德森 (Steve Sanderson) 有一个较旧的示例,演示如何在您的 Controller 操作中正确绑定(bind)提交的 JSON 数据:http://blog.stevensanderson.com/2010/07/12/editing-a-variable-length-list-knockout-style/

要点是他创建了一个名为“FromJson”的属性,如下所示:

public class FromJsonAttribute : CustomModelBinderAttribute
{
    private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer();

    public override IModelBinder GetBinder()
    {
        return new JsonModelBinder();
    }

    private class JsonModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
            if (string.IsNullOrEmpty(stringified))
                return null;
            return serializer.Deserialize(stringified, bindingContext.ModelType);
        }
    }
}

然后, Action 看起来像:

    [HttpPost]
    public ActionResult Index([FromJson] IEnumerable<GiftModel> gifts)

此外,如果您不喜欢必须使用该属性,那么您实际上可以注册一个类型以始终使用特定的模型绑定(bind)器。

您可以创建一个如下所示的模型 Binder :

public class JsonModelBinder: IModelBinder
{
    private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer();

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
        if (string.IsNullOrEmpty(stringified))
            return null;
        return serializer.Deserialize(stringified, bindingContext.ModelType);
    }
}

然后,在 global.asax.cs 中注册它,例如:

ModelBinders.Binders.Add(typeof(DocumentModel), new JsonModelBinder());

现在,您不需要使用属性,您的 DocumentModel 将被正确绑定(bind)。这意味着您将始终通过 JSON 发送 DocumentModel。

关于asp.net-mvc - 如何对 MVC 3 应用程序进行表单 POST 并获取反序列化类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6793377/

相关文章:

使用 Golang 发布 HTML 表单方法

internet-explorer - IE 的 foreach 更快

c# - 无法先从模型代码中删除 FK

asp.net-mvc - Knockout js - 脏标志问题

c# - MVC 页面未显示,404 未找到

php - 仅限 'POST' 类型的默认特色图片(不包括 'page' )

asp.net-mvc - RadioButton用于不在编辑器模板中选择值

reactjs - 从 Chalice API 获取

data-binding - 如何在下拉 knockout js中预先选择一个选项

javascript - 如何将从 json 接收到的 ko.observable 字符串解析为整数(数字)值