如何使用SYNCHRONOUS页面POST从HTML表单发送复杂的JSON对象?

我的服务器正在使用ServiceStack,并希望收到一些这样的数据:

{ Customer: { Company: "TheCompany", RegionCode: "AU_NSW" }, Name: { First: "Jimi", Last: "Hendrix" } } 

我有一个包含这些字段的表单,我可以使用JQuery轻松获取数据,创建嵌套的JSON对象并使用$ .post发送它。

但我不想将其作为AJAX发送,因为我希望整个页面都提交,然后浏览器将服务器的响应显示为新页面。 只是经典的forms发布行为。

我已经尝试将复杂的json作为字符串嵌入隐藏的表单字段中 – 没有雪茄。

我还查看了ServiceStack是否有任何命名约定,以便我可以调用我的表单字段“Name [First]”并让ServiceStack将正确的值放在正确的嵌套结构中 – 也就是没有雪茄。

  1. 有没有办法可以在表单发送数据之前将JSON对象附加到表单的POST数据? 要么
  2. 有没有办法我可以使用jQuery进行整页提交(所以我可以发送一个复杂的嵌套JSON,同时仍然有正常的“页面提交”行为)?

虽然Mythz建议发布JSV值会起作用,但在JavaScript中构建和维护复杂的JSV有时会很麻烦。 例如,您可能必须处理转义用户输入的数据,并且语法问题可能难以跟踪

这个解决方案看起来很复杂,但实际上并非如此,并且高度可重用,只需要您可以发送编码的JSON,jQuery非常容易。

完整的演示源代码在这里

流程 – 工作原理:

  1. 您的jQuery使用提交时的表单数据创建DTO
  2. DTO编码为JSON,只需使用JSON.stringify(data)
  3. JSON以隐藏forms发送,作为Data字段的值
  4. 服务器DTO属性filter将Data字段的JSON值反序列化到DTO中
  5. 您的服务会看到正常填充的DTO。

过滤属性:

我的解决方案将表单邮件中编码为JSON的DTO对象发送到服务。 然后,一个简单的filter拦截请求并从JSON有效负载填充DTO。

 public class GetFromJsonVariableAttribute : Attribute, IHasRequestFilter { string _variableName; public GetFromJsonVariableAttribute(string variableName = "Data") { _variableName = variableName; } public void RequestFilter(IRequest req, IResponse res, object requestDto) { // Convert the JSON payload to DTO format var payload = req.GetParam(_variableName); if(payload != null) requestDto = JsonSerializer.DeserializeFromString(payload, requestDto.GetType()); } public int Priority { get { return int.MinValue; } } IHasRequestFilter IHasRequestFilter.Copy() { return this; } } 

用法

然后使用您只需将属性添加到您的DTO。 Data是保存JSON有效内容的表单变量的名称。 您可以在此处选择任何您想要的名称。

 [GetFromJsonVariable("Data")] [Route("/Customers","POST")] public class CreateCustomerRequest : IReturnVoid { public Customer Customer { get; set; } public Name Name { get; set; } } 

客户端(jQuery):

  1. 获取您的表单值
  2. 将所需的DTO结构构建为JavaScript对象
  3. 将该DTO转换为JSON字符串
  4. 将隐藏的表单值设置为DTO字符串并提交
 $("#CreateCustomer").on("submit", function(){ // Get the form values into simple key value array var values = {}; $.each($(this).serializeArray(), function(){ values[this.name] = this.value; }); // Prepare the DTO var data = { Customer: { Company: values["Company"], RegionCode: values["RegionCode"] }, Name: { First: values["First"], Last: values["Last"] } }; // Convert it to JSON $('#PayloadForm [name="Data"]').val(JSON.stringify(data)); $('#PayloadForm').submit(); return false; }); 

使用HTML创建用户将与之交互的表单,无需任何操作,但链接到jQuery提交事件代码; 以及一个实际执行同步POST的隐藏表单。 请注意,属性Data与应接收有效负载的属性的属性相匹配

 




ServiceStack可以使用JSV格式POST复杂类型 ,例如:

   

否则,您可以使用JSON发送复杂类型,例如使用jQuery的$ .ajax:

 $.ajax({ type: 'POST', contentType: 'application/json; charset=utf-8', url: "http://host/myservice", dataType: 'json', data: JSON.stringify({Customer:{Company:'x',RegionCode:'x'}}), success: function(response){ ... } }); 

虽然为了实现最大的互操作性,您应该努力使您的请求DTO保持平稳,例如:

 

然后您可以使用x-www-form-urlencoded Content-Type进行POST操作,或使用ServiceStack的ss-utils.js bindForm方法进行ajaxify ,例如:

 $("#theForm").bindForm(); 

将提交处理程序附加到表单,该表单将JSON作为表单中预先创建的隐藏输入字段的值。

 $(form_to_submit).on('submit', function() { $(form_to_submit).find(hidden_input).val(json_value); }); 

要使用jQuery提交表单,请使用:

 $(form_to_submit).submit(); 

我在这里遇到了同样的问题,我在使用NodeJS和Express Server。 我想发布一个复杂的JSON对象,我已经构建为用户选择的客户端。 然后我将onClick事件附加到一个调用我的SubmitForm函数的按钮。

您的数据可以是任何JSON对象。 请务必解析服务器端。

 function Param(name, value){ var hiddenField = document.createElement('input'); hiddenField.setAttribute('type', 'hidden'); hiddenField.setAttribute('name', name); hiddenField.setAttribute('value', value); return hiddenField; } function SubmitForm(data){ var form = document.createElement('form'); form.setAttribute('method', 'post'); form.setAttribute('action', '/route'); form.appendChild(Param('data', JSON.stringify(data))); document.body.appendChild(form); form.submit(); } 

另外,这是纯粹的javascript。 对于那些喜欢消除开销的人来说,这里没有隐藏的HTML或jQuery。