跨页面提交JSON对象的解决方案

在Web开发中,经常需要将数据从一个页面提交到另一个页面。本文将介绍如何在ASP.NET MVC框架中实现这一功能,特别是如何将一个JSON对象从一个控制器动作提交到另一个控制器动作,并实现页面跳转。

问题描述

目标是从一个页面提交一个JSON对象到另一个页面,并在提交后跳转到目标页面。这个过程涉及到从一个控制器动作到另一个控制器动作的数据传递。

[HttpPost] public ActionResult SubmitOrder(OrderViewModel vmOrder) { // 处理vmOrder return View(vmOrder); } function CollectOrderDetails() { var order = new Object(); // 填充订单数据 // 将订单对象序列化后提交到目标页面 JSON.stringify(order); }

可能的解决方案

要实现提交操作(POST),有以下几种选择:

使用jQuery的.post或.ajax方法,并设置content-type为"application/json",可以将序列化的订单对象发送到目标控制器动作。ASP.NET MVC会自动将JSON对象反序列化为OrderViewModel。但问题在于,这是Ajax调用,响应会在Ajax的xhr对象中返回,因此不会发生页面跳转。

这种方法与前一种类似,区别在于当响应从xhr对象返回时(在这种情况下,响应是一个代表目标页面的完整HTML响应),将其注入到文档中。这种方法的问题在于,它会返回HTML和JavaScript,但不会被解析,仍然停留在源页面(URL将保持不变),并且只显示了目标页面。这种方法最适合处理部分视图,或者处理返回静态内容且不包含需要解析的脚本标签的页面。

这种方法是创建一个表单元素,在JavaScript中创建一个隐藏的HTML input元素,将订单对象序列化并存储在隐藏字段中,将隐藏的input元素附加到表单并提交。

var form = document.createElement("form"); var input = document.createElement("input"); input.setAttribute("type", "hidden"); input.setAttribute("name", "XOrder"); input.setAttribute("value", JSON.stringify(order)); form.appendChild(input); document.body.appendChild(form); form.submit();

最佳解决方案

希望实现的是不使用Ajax的正常表单提交(POST),并希望控制器动作的参数自动反序列化为视图模型参数(OrderViewModel)。为了实现这一点,需要更深入地了解ASP.NET MVC中的模型绑定器,模型绑定器负责将传入MVC控制器的HTTP请求转换为控制器可以理解和处理的对象。

public class JsonModelBinder : DefaultModelBinder { public override BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { try { var strJson = controllerContext.HttpContext.Request.Form[bindingContext.ModelName]; if (string.IsNullOrEmpty(strJson)) { return null; } else { JavaScriptSerializer serializer = new JavaScriptSerializer(); var model = serializer.Deserialize(strJson, bindingContext.ModelType); var modelMetaData = ModelMetadataProviders.Current.GetMetadataForType(() => model, bindingContext.ModelType); var validator = ModelValidator.GetModelValidator(modelMetaData, controllerContext); var validationResult = validator.Validate(null); foreach (var item in validationResult) { bindingContext.ModelState.AddModelError(item.MemberName, item.Message); } return model; } } catch (Exception ex) { bindingContext.ModelState.AddModelError(bindingContext.ModelType.Name, ex.Message); } } }

首先,将JsonBinder属性添加到目标控制器动作的参数上:

[HttpPost] public ActionResult SubmitOrder([JsonBinder] OrderViewModel vmOrder) { // 处理vmOrder return View(vmOrder); }

其次,当从JavaScript发送数据时,将隐藏字段的名称设置为参数的名称:

var form = document.createElement("form"); var input = document.createElement("input"); input.setAttribute("type", "hidden"); input.setAttribute("name", "vmOrder"); input.setAttribute("value", JSON.stringify(order)); form.appendChild(input); document.body.appendChild(form); form.submit();
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485