ASP.NET MVC如何传递单条ViewModel数据及防伪令牌至控制器?
解决ASP.NET MVC中AJAX传递单条ViewModel数据并携带防伪令牌的问题
嘿,我看你这问题是AJAX传单条数据到MVC Controller时模型绑定失败,还得带防伪令牌对吧?核心问题是你传递的数据格式和MVC模型绑定器的预期不匹配,再加上防伪令牌在不同请求格式下的传递方式有区别,导致Model一直为空。我给你两种可行的解决方案,你按需选:
方案一:用JSON格式传递(推荐)
这种方式更适合复杂对象的传递,步骤如下:
1. 修改前端AJAX代码
主要调整点:
- 直接序列化选中的员工对象,不要额外包一层
{employee} - 设置
contentType: "application/json; charset=utf-8",告诉服务器请求体是JSON - 把防伪令牌放在请求头里(因为JSON格式的请求体没法同时带表单字段)
修改后的save函数:
function save() { var selectedEmpId = 1; // 这里替换成你实际选中的员工ID,别一直用0哦 var employeeList = @Html.Raw(Json.Encode(Model)); // filter返回的是数组,要取第一个匹配的元素 var employee = employeeList.filter(function (e) { return e.Id === selectedEmpId; })[0]; if (!employee) { alert('请先选择一个员工'); return; } var token = $('[name=__RequestVerificationToken]').val(); $.ajax({ type: "POST", url: '@Url.Action("Save", "Employee")', cache: false, contentType: "application/json; charset=utf-8", // 必须设置这个 data: JSON.stringify(employee), // 直接序列化选中的员工对象 headers: { // 把防伪令牌放在请求头,MVC默认会识别这个键 'RequestVerificationToken': token }, success: function (result) { console.log('保存成功:', result); // 这里可以加成功后的页面逻辑,比如刷新列表 }, error: function (xhr) { console.error('保存失败:', xhr.responseText); } }); };
2. 调整Controller Action(可选但建议)
给参数加上[FromBody]特性,明确告诉模型绑定器从请求体中获取数据(虽然MVC默认会这么做,但加上更清晰):
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Save([FromBody] DemoViewModel model) { if (ModelState.IsValid) { // 你的业务逻辑 return Json(new { success = true, message = "保存成功" }); } // 返回错误信息给前端 var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage); return Json(new { success = false, errors = errors }); }
方案二:用表单键值对传递
如果你的ViewModel属性不多,也可以把属性拆成键值对传递,这种方式不需要设置contentType,防伪令牌直接放在data里就行:
修改前端AJAX代码
function save() { var selectedEmpId = 1; var employeeList = @Html.Raw(Json.Encode(Model)); var employee = employeeList.filter(function (e) { return e.Id === selectedEmpId; })[0]; if (!employee) { alert('请先选择一个员工'); return; } var token = $('[name=__RequestVerificationToken]').val(); $.ajax({ type: "POST", url: '@Url.Action("Save", "Employee")', cache: false, // 不用设置contentType,默认就是application/x-www-form-urlencoded data: { Id: employee.Id, Name: employee.Name, Surname: employee.Surname, Town: employee.Town, __RequestVerificationToken: token }, success: function (result) { console.log('保存成功:', result); }, error: function (xhr) { console.error('保存失败:', xhr.responseText); } }); };
Controller Action无需修改
原来的Action代码直接用就行,因为表单格式的数据模型绑定器能直接解析。
为什么你之前的代码不行?
- 数据格式错误:你把序列化后的JSON字符串放在
model参数里传递,MVC会把model当成一个普通字符串,而不是DemoViewModel对象,自然绑定失败。 - contentType不匹配:当你设置
contentType: "application/json"时,却把数据包装成{model: formdata},这不是标准的JSON格式,服务器没法解析。 - 防伪令牌传递方式错误:在JSON格式请求下,把令牌放在data里会导致请求体同时包含JSON和表单字段,服务器无法同时解析两种格式,所以必须放在请求头里。
内容的提问来源于stack exchange,提问作者user5871859
相关产品推荐
相关产品推荐

