You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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代码直接用就行,因为表单格式的数据模型绑定器能直接解析。

为什么你之前的代码不行?

  1. 数据格式错误:你把序列化后的JSON字符串放在model参数里传递,MVC会把model当成一个普通字符串,而不是DemoViewModel对象,自然绑定失败。
  2. contentType不匹配:当你设置contentType: "application/json"时,却把数据包装成{model: formdata},这不是标准的JSON格式,服务器没法解析。
  3. 防伪令牌传递方式错误:在JSON格式请求下,把令牌放在data里会导致请求体同时包含JSON和表单字段,服务器无法同时解析两种格式,所以必须放在请求头里。

内容的提问来源于stack exchange,提问作者user5871859

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:17:30