Asp.Net Core中如何通过Ajax向MVC控制器同时传递表单对象与参数
问题描述
通过$('#SearchProduct').serialize()序列化得到的表单数据,需要和额外分页参数一起传递到MVC控制器,但无论怎么调整传参方式,始终只有一个参数能被控制器成功绑定接收,尝试过JSON.stringify(ObjSearch, page)处理参数依然无法解决。
现有代码
jQuery 事件绑定代码
const MainProducts = new Products(); MainProducts.LoadProducts(null, 1); Search_Btn.click(function () { const Form_Data = SearchProduct.serialize(); MainProducts.LoadProducts(Form_Data, 1); });
Ajax 请求封装代码
LoadProducts(ObjSearch, page) { console.log(page); $.ajax({ url: GetUrlAdmin.Product.AllShowProducts, type: "Get", beforeSend: function (xhr) { xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val()); }, data: { ObjSearch, page }, dataType: 'json', contentType: 'application/json;charset=utf-8', success: function (result) { // 业务处理逻辑 }) }
控制器 Action 代码
public async Task<JsonResult> GetAllShowProducts(ProductSearchViewModel model, int page) { var Products = await _admin.GetAllShowProducts(model, page); return Json(new { data = Products }); }
问题原因
- 配置不匹配:当前用的是
Get请求,参数默认拼在URL查询字符串中传递,根本不需要设置contentType: 'application/json;charset=utf-8',这个配置是给POST请求传JSON请求体用的,GET请求带这个配置会打乱jQuery默认的参数序列化逻辑。 - 序列化格式处理错误:
serialize()返回的是key1=val1&key2=val2格式的URL编码字符串,直接把这个字符串作为ObjSearch字段放到data对象里,jQuery会把整个字符串当成ObjSearch的单个值编码,不会把表单字段拆出来绑定到ProductSearchViewModel的对应属性上。 - API用法错误:
JSON.stringify的第二个参数是序列化过滤规则(替换函数/属性白名单),不是用来拼接第二个业务参数的,写JSON.stringify(ObjSearch, page)根本不会把page参数带入序列化结果,反而会导致序列化逻辑异常。
解决方案
两种方案选其一即可,优先选改动最小的方案1。
方案1:保持GET请求,直接拼接参数(无需改后端代码)
去掉GET请求多余的contentType配置,把page参数直接拼到表单序列化生成的参数字符串后面,让所有参数统一以URL查询参数的形式传递,MVC默认模型绑定器会自动完成参数拆分绑定:
LoadProducts(ObjSearch, page) { console.log(page); $.ajax({ url: GetUrlAdmin.Product.AllShowProducts, type: "Get", beforeSend: function (xhr) { xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val()); }, // 拼接参数,无表单数据时只传page data: ObjSearch ? `${ObjSearch}&page=${page}` : `page=${page}`, dataType: 'json', success: function (result) { // 业务处理逻辑 } }) }
方案2:改用POST请求传JSON(适合复杂参数场景)
如果后续要传递的参数结构更复杂,可以改成POST请求,先把serialize()生成的字符串转成JS对象,加上page参数后统一序列化成JSON传递:
- 先加一个工具方法把序列化字符串转成JS对象:
function serializeToObj(str) { if(!str) return {}; return Object.fromEntries(new URLSearchParams(str)); } - 修改Ajax逻辑:
LoadProducts(ObjSearch, page) { console.log(page); $.ajax({ url: GetUrlAdmin.Product.AllShowProducts, type: "Post", beforeSend: function (xhr) { xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val()); }, contentType: 'application/json;charset=utf-8', data: JSON.stringify({ ...serializeToObj(ObjSearch), page: page }), dataType: 'json', success: function (result) { // 业务处理逻辑 } }) } - 后端调整:因为POST传JSON时
[FromBody]默认只能绑定一个参数,建议直接给ProductSearchViewModel增加int Page { get; set; }属性,Action改成接收单个模型参数即可,绑定更稳定。
内容的提问来源于stack exchange,提问作者sunboy_sunboy
相关产品推荐
相关产品推荐

