ASP.NET Core MVC Ajax上传文件返回400 Bad Request问题
解决Ajax上传分部视图表单文件时的400 Bad Request问题
你的问题主要出在模型绑定方式、FormData的传递逻辑以及防伪造Token的处理上,下面一步步帮你修正:
1. 修正Action的模型绑定特性
你当前用了[FromBody],但上传文件用的是multipart/form-data格式的表单数据,而非JSON,这个特性会导致ASP.NET Core无法正确解析FormData中的文件,直接返回400错误。
修改后的Action代码:
[HttpPost] [ValidateAntiForgeryToken] // 显式启用防伪造验证,确保安全 public async Task<IActionResult> UploadFile([FromForm] ApplicationsFileCreateInputModel createInputModel) { var fileId = await applicationFileService.UploadAsync(createInputModel); return Json(fileId); }
2. 给分部视图表单添加防伪造Token
你的表单没有生成防伪造Token的隐藏域,需要手动添加(ASP.NET Core的asp-form标签助手会自动生成,但你用的是普通<form>):
修改后的分部视图代码:
@using ArkStore.App.Models.BindingModels.ApplicationFiles @model ApplicationsFileCreateInputModel <form enctype="multipart/form-data" method="post"> @Html.AntiForgeryToken() <!-- 新增这一行,生成防伪造Token隐藏域 --> <div class="custom-file w-50 mb-2"> <label class="custom-file-label" asp-for="AppApk"></label> <input class="custom-file-input" asp-for="AppApk" id="appApk" type="file"> <span asp-validation-for="AppApk" class="text-danger"></span> </div> <div class="custom-file w-50 mb-2"> <label class="custom-file-label" asp-for="Thumbnail"></label> <input class="custom-file-input" asp-for="Thumbnail" id="thumbnail" type="file"> <span asp-validation-for="Thumbnail" class="text-danger"></span> </div> <div class="form-group"> <button id="upload" type="submit" class="btn btn-primary">Upload</button> </div> </form>
3. 修正Ajax的FormData传递逻辑
之前你把FormData嵌套在data字段里,还单独传递Token,这会导致服务器无法正确解析表单数据。正确的做法是直接把包含Token的FormData作为请求数据发送:
修改后的Ajax代码:
function setUploadFileId() { const targetForm = document.forms[1]; const formData = new FormData(targetForm); // 直接从表单创建FormData,自动包含Token和文件 $.ajax({ url: "https://localhost:44377/Applications/UploadFile", type: "POST", data: formData, contentType: false, // 让浏览器自动设置正确的multipart/form-data头 processData: false, // 不要处理FormData,避免jQuery自动序列化 success: function (id) { $("#fileId").val(id); }, error: function (error) { console.log(error); } }); } $("#upload").on("click", function (evt) { evt.preventDefault(); setUploadFileId(); });
关键问题解释
- [FromBody] vs [FromForm]:
[FromBody]用于解析请求体中的JSON数据,而文件上传用的是表单格式,必须用[FromForm]才能正确绑定IFormFile类型的参数。 - 防伪造Token的传递:Token必须包含在FormData中一起发送,通过
@Html.AntiForgeryToken()生成的隐藏域会被自动加入FormData,服务器才能验证通过。 - contentType和processData设置:这两个参数设为
false是为了让浏览器自动处理multipart/form-data的请求头和边界,避免jQuery对FormData做错误的序列化。
你可以在浏览器开发者工具的网络标签里查看请求,确认FormData中包含了两个文件和__RequestVerificationToken,这样就能正常上传了。
内容的提问来源于stack exchange,提问作者User001
相关产品推荐
相关产品推荐

