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

ASP.NET通过AJAX传文件到控制器时附件为null的解决方法

问题根因

你现在的代码有3个核心问题导致文件和数据接收失败:

  • 错误将FormData对象放入JSON中做序列化,JSON格式无法承载二进制文件数据,同时手动指定contentType: 'application/json',让请求以JSON格式发送,完全丢失了multipart格式的文件段,后端自然读不到Request.Files
  • 模型中ATTACHMENT字段定义为string类型,根本无法接收二进制文件对象
  • ajax未配置processData: false,jQuery会默认将传入的FormData对象转成查询字符串,直接破坏文件结构;同时FormData内的字段名和后端模型的属性、参数结构不匹配,模型绑定无法正常映射字段
修复步骤

1. 调整模型类的文件字段类型

文件不能用string类型接收,需要根据你用的MVC版本替换成对应文件类型:

  • 如果是.NET Framework 版本的ASP.NET MVC 5:
public class SnapShotReceivedData
{
    public string REASON { get; set; }
    public string COMMENT { get; set; }
    public HttpPostedFileBase ATTACHMENT { get; set; }
    // 多文件上传就改成 public List<HttpPostedFileBase> ATTACHMENT { get; set; }
}
  • 如果是ASP.NET Core MVC:
public class SnapShotReceivedData
{
    public string REASON { get; set; }
    public string COMMENT { get; set; }
    public IFormFile ATTACHMENT { get; set; }
    // 多文件上传就改成 public List<IFormFile> ATTACHMENT { get; set; }
}

2. 重写前端提交逻辑

核心要求:不要做JSON序列化,不要手动设置Content-Type,所有普通字段和文件都追加到同一个FormData实例中,修正后的代码如下:

function submit()
{
    var REASON_EXEMPT= $('#reasonexe').val();
    var COMMENT_EXEMPT= $('#txtCommentexe').val();
    var $file = document.getElementById('file');
    var $formData = new FormData();

    // 追加普通字段,键名必须和后端参数、模型属性结构完全匹配
    // 如果控制器参数改成单个对象而非List,直接去掉sObject[0].前缀即可
    $formData.append("sObject[0].REASON", REASON_EXEMPT);
    $formData.append("sObject[0].COMMENT", COMMENT_EXEMPT);
    
    // 追加文件
    if ($file.files.length > 0) {
        // 单文件直接追加
        $formData.append("sObject[0].ATTACHMENT", $file.files[0]);
        // 多文件就循环追加到同一个键名
        // for (var i = 0; i < $file.files.length; i++) {
        //     $formData.append("sObject[0].ATTACHMENT", $file.files[i]);
        // }
    }

    $.ajax({
        contentType: false, // 让浏览器自动生成multipart/form-data请求头和正确的分隔符
        processData: false, // 禁止jQuery转码FormData对象
        dataType: 'json',
        type: 'POST',
        url: '@Url.Action("SetHCMNIDSnapData", "Home")',
        data:  $formData,
        success: function (result) {                   
            if (result=='10') {
                // 对应业务逻辑
            }
            if (result == '12') {
                // 对应业务逻辑
            }
        },
        error: function (response) {
            // 错误处理逻辑
        }
    });
}

如果你不需要提交多条数据,只传单条记录,可以直接把控制器参数改成SnapShotReceivedData sObject,前端FormData追加字段时直接用REASON/COMMENT/ATTACHMENT作为键名即可,不需要加sObject[0].前缀。

3. 修正控制器动作方法

给方法加POST请求标记,不需要手动读取Request.Files,模型绑定会自动映射文件到属性:

  • .NET Framework MVC 版本:
[HttpPost]
public JsonResult SetHCMNIDSnapData(List<SnapShotReceivedData> sObject)
{
    if (sObject != null && sObject.Count > 0 && sObject[0].ATTACHMENT != null)
    {
        // 直接取文件属性即可
        string fileName = sObject[0].ATTACHMENT.FileName;
        int fileSize = sObject[0].ATTACHMENT.ContentLength;
        // 自定义文件保存逻辑
    }
    // 你的业务逻辑
    return Json(10);
}
  • ASP.NET Core 版本,需要给参数加[FromForm]标记明确绑定来源:
[HttpPost]
public JsonResult SetHCMNIDSnapData([FromForm]List<SnapShotReceivedData> sObject)
{
    // 逻辑和上述一致,直接从sObject[0].ATTACHMENT取文件即可
}
关键注意点
  • 所有带文件上传的POST请求,必须使用multipart/form-data编码,不能用application/json,JSON格式本身不支持二进制内容传输
  • 用jQuery+FormData传文件时,必须设置processData:false和contentType:false,否则请求会被错误转码导致文件丢失
  • FormData中追加的字段名必须和后端模型的属性名、参数层级完全匹配,传集合类型时需要带[索引]前缀才能被模型绑定正确识别

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:40:37