将序列化表单数据和附加数据发布到MVC控制器?

时间:2014-02-13 21:54:15

标签: c# javascript asp.net-mvc

我正在尝试将POST请求发送到我的服务器的其他一些数据。最初,我只发送了几种形式的信息:

$.ajax({
    url: 'SaveAllDetails',
    type: 'POST',
    data: $('form').serialize(),
    dataType: 'json'
});

和MVC Controller方法:

[HttpPost]
public ActionResult SaveAllDetails([Bind(Prefix = "order")]ExistingOrderDetailsModel existingOrderDetailsModel, 
    [Bind(Prefix = "task")]ExistingTaskDetailsModel existingTaskDetailsModel, [Bind(Prefix = "device")]DeviceDetailsModel deviceDetailsModel)
{
    ....
}

这很有效。 MVC的模型绑定器能够正确地反序列化URL编码的字符串。

现在,要求已经改变。我需要发送一个额外的数据数组以及我的三个表单。此数据数组不保存在表单中,并且没有绑定前缀。我需要在同一个Controller方法中完成所有操作,因为所有验证都需要在单个事务中执行。

所以,我现在得到了:

var subcomponentsGridRows = JSON.stringify(subcomponentsDetailsView.getAllGridData());
var existingOrderDetailsFormData = $('form#existingOrderDetailsForm').serialize();
var existingTaskDetailsFormData = $('form#existingTaskDetailsForm').serialize();
var deviceDetailsFormData = $('form#existingDeviceDetailsForm').serialize()

$.ajax({
    url: 'SaveAllDetails',
    type: 'POST',
    data: {
        existingOrderDetailsModel: existingOrderDetailsFormData,
        existingTaskDetailsModel: existingTaskDetailsFormData,
        deviceDetailsModel: deviceDetailsFormData,
        subcomponentsGridRows: subcomponentsGridRows
    },
    dataType: 'json'
});

至少有一个原因,这不起作用。每个表单都表示为URL编码的字符串。 subcomponentsGridRows是一个JSON结构。据我所知,MVC模型绑定器无法一次性解密这两种类型的信息。

解决这个问题的好方法是什么?

1 个答案:

答案 0 :(得分:13)

您可能会发现following plugin有用。

以下是它对您有用的方式。让我们首先通过定义视图模型来清理控制器操作:

public class MyViewModel
{
    public ExistingOrderDetailsModel Order { get; set; }
    public ExistingTaskDetailsModel Task  { get; set; }
    public DeviceDetailsModel Device  { get; set; }

    public AdditionalRowsViewModel[] AdditionalRows { get; set; }
}

在此示例中,AdditionalRowsViewModel显然会保存您尝试传递给控制器​​操作的其他信息。

然后您的控制器操作将变为:

[HttpPost]
public ActionResult SaveAllDetails(MyViewModel model)
{
    ....
}

好的,这一步是绝对必要的,只是当我看到控制器动作占用多于1个参数时,我只需定义一个视图模型。

最后让我们调整我们的AJAX调用:

$.ajax({
    url: 'SaveAllDetails',
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({
        order: $('form#existingOrderDetailsForm').serializeObject(),
        task: $('form#existingTaskDetailsForm').serializeObject(),
        device: $('form#existingDeviceDetailsForm').serializeObject(),
        additionalRows: subcomponentsDetailsView.getAllGridData()
    }),
    success: function(result) {
        // do something with the result of the AJAX call here
    }
});

需要注意的事项:

  1. 在AJAX请求中删除此dataType: 'json'参数。您正在使用ASP.NET MVC和希望您从控制器操作返回Jsonresult,该操作成功将Content-Type响应标头设置为正确的值。 jQuery足够智能,可以使用此响应头的值并预处理将传递给AJAX请求的result回调的success变量。所以在这种情况下你将获得一个javascript对象
  2. 由于您要在AJAX请求中向服务器发送JSON,因此您需要正确指定contentType: application/json参数。否则,您如何期望ASP.NET MVC知道客户端正在发送JSON并应用正确的模型绑定器?顺便说一下,jQuery将发送的默认Content-Type请求标头是application/x-www-form-urlencoded,因此如果您在POST请求中发送JSON有效负载,那将是冲突并违反协议。