我的服务器正在使用 ServiceStack,并且希望接收如下数据:
{
Customer: {
Company: "TheCompany",
RegionCode: "AU_NSW"
},
Name: {
First: "Jimi",
Last: "Hendrix"
}
}
我有一个包含这些字段的表单,我可以使用 JQuery 轻松获取数据,创建嵌套的 JSON 对象并使用 $.post 发送它。
但我不想将其作为 AJAX 发送,因为我希望提交整个页面,然后浏览器将服务器的响应显示为新页面。只是经典的表单发布行为。
我尝试将复杂的 json 作为字符串嵌入隐藏表单字段中 - 没有雪茄。
我还查看了 ServiceStack 是否有任何命名约定,以便我可以将我的表单字段称为“Name[First]”,并让 ServiceStack 将正确的值放入其正确的嵌套结构中 - 也没有雪茄。
- 有没有办法可以在表单发送数据之前将 JSON 对象附加到表单的 POST 数据? 或
- 有没有办法可以使用 jQuery 进行整页提交(这样我就可以发送复杂的嵌套 JSON,同时仍然具有正常的“页面提交”行为)?
最佳答案
虽然 Mythz 关于发布 JSV 值的建议可行,但有时在 JavaScript 中构建和维护复杂的 JSV 会很麻烦。 例如,您可能必须处理转义用户输入的数据,并且语法问题可能很难跟踪
这个解决方案看起来很复杂,但实际上并不复杂,并且具有高度可重用性,并且只需要您可以发送编码的 JSON,这在 jQuery 中非常简单。
Full Demo Source Code Here
流程 - 工作原理:
- 您的 jQuery 使用提交时的表单数据创建 DTO
- DTO 被编码为 JSON,只需使用
JSON.stringify(data)
- JSON 以隐藏形式作为
Data
字段的值发送 - 服务器 DTO 属性过滤器将
Data
字段的 JSON 值反序列化到您的 DTO - 您的服务会看到 DTO 已正常填充。
过滤属性:
我的解决方案将编码为 JSON 的 DTO 对象以表单发布的形式发送到服务。然后,一个简单的过滤器拦截请求并从 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):
- 获取表单值
- 将所需的 DTO 结构构建为 JavaScript 对象
- 将该 DTO 转换为 JSON 字符串
- 将隐藏表单值设置为 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
属性与应接收负载的属性相匹配
<form id="CreateCustomer">
<input type="text" name="Company" value="TheCompany" /><br/>
<input type="text" name="RegionCode" value="AU_NSW" /><br/>
<input type="text" name="First" value="Jimi" /><br/>
<input type="text" name="Last" value="Hendrix" /><br/>
<input type="submit" value="Submit" />
</form>
<!-- This form is hidden -->
<form action="/Customers" method="POST" id="PayloadForm">
<input type="hidden" name="Data" value="">
</form>
关于javascript - 如何使用同步页面 POST 从 HTML 表单发送复杂的 JSON 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23355017/