2014-02-13 68 views
6

我试图抓住一些额外的数据POST请求发送到我的服务器。最初,我只发送几种形式的信息价值:将序列化表单数据和附加数据发布到MVC控制器?

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

和MVC控制器方法:

[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模型绑定器无法一次破译这两种类型的信息。

解决此问题的最佳方法是什么?

+0

'subcomponentsGridRows是一个JSON结构,并且MVC模型绑定器不能破译那个混乱'。怎么会这样?如果您创建了一个代表此结构的模型(例如,使用此网站:http://json2csharp.com/),则模型活页夹将会愉快地绑定它。 –

+0

你可以在提交之前合并数据或在POST URL中使用GET来传递其他信息... – dandavis

+0

@SimonWhitehead当我将数据发布到服务器时,我必须指出我要发送什么类型的信息。这些表单是URL编码的实体。网格数据是一个JSON结构。 MVC会乐意接受其中一个,但据我所知,在一个请求中并不是一个简单的方法来结合它们。 –

回答

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) 
{ 
    .... 
} 

OK,这一步是绝对必要的,它只是当我看到一个控制器动作时超过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足够智能,可以使用此响应头的值并预处理result变量,该变量将传递给您的AJAX请求的success回调。因此,在这种情况下,您将获得一个javascript对象
  2. 由于您在发送AJAX请求中的服务器时发送JSON,因此您需要正确指定contentType: application/json参数。否则,你如何期望ASP.NET MVC会知道客户端正在发送JSON并应用正确的模型绑定器?顺便说一下,jQuery将发送的默认内容类型请求标头是application/x-www-form-urlencoded,因此如果您在POST请求中发送JSON有效内容,这将是冲突和违反协议。
+0

您的解决方案如何考虑表单前缀?我无法将个别前缀绑定到MyViewModel的每个属性。据我所知,前缀必须与个别参数或整个类相关联。我应该修改serializeObject去除“订单”,“任务”。和“设备”。键的前缀? –

+0

如果属性名称是唯一的,那么您确实可以修改插件以将其考虑在内并将其删除。或者,您可以更新它以生成复杂的JSON子对象。 –

+0

属性名称对于每个对象都是唯一的,但在表单之间不唯一。我认为这对解决方案来说是可以的,但是因为一旦每个表单被分离到一个给定的对象中,它就是非模糊的。当我有我的最终解决方案时,我会更新,但谢谢你,这似乎是正确的方式。干杯。 –

相关问题