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

ASP.NET Core Razor Pages中Ajax POST到同页面事件处理器报400错误

问题描述

使用.NET 8和VS2022开发ASP.NET Core Razor Pages,为避免控制器暴露给公众,所有POST请求均指向同页面的事件处理器(如www.mywebsite.com/index调用该页的ASP.NET Core事件处理器)。遇到以下问题:

  • 场景1:Ajax POST上传文件时,携带防伪令牌调用控制器可成功,但调用同页面事件处理器失败;
  • 场景2:上传文件到index页时触发400错误,尝试过IActionResult返回值及ImageUpload类(代码已注释),均得到相同结果。

后端代码

//public async Task<IActionResult> OnPostAsync(ImageUpload imageUpload)
public async Task OnPostAsync()
{
    var file = Request.Form.Files[0];
    var fileName = Path.GetFileName(file.FileName);
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads", fileName);

    using (var fileStream = new FileStream(filePath, FileMode.Create))
    {
        await file.CopyToAsync(fileStream);
    }

    //return Content($"File '{fileName}' uploaded successfully.");
}

前端代码(已尝试JSON.stringify但无效)

$('#fileInput').change(function () {
    var token = $('#__RequestVerificationToken').val();
        
    var file = this.files[0];

    if (file) {
        var reader = new FileReader();
        var formData = new FormData();
        formData.append('file', file);
        reader.onload = function (e) {
            $('#previewImage').attr('src', e.target.result).show();

            var formData = new FormData();
            formData.append('file', file);
            var formData2 = JSON.stringify(formData);
            $.ajax({
                type: "POST",
                url: "",//this enables it to post to the root
                contentType: "application/json",
                processData: false,
                data: formData2,
                headers: {
                            RequestVerificationToken: token
                        },
                success: function (response) {
                    console.log('File uploaded successfully');
                },
                error: function (xhr, status, error) {
                    console.error('Error uploading file:', error);
                }
            });
        };
    }
});

HTML代码

<form>
 @Html.AntiForgeryToken()
<p>
    <input type="file" id="fileInput" accept="image/*">

    <br><br>
    <img src="" id="previewImage" style="max-width: 300px; max-height: 300px; display: none;">
</p>
</form>

解决方案

1. 修复前端FormData与请求格式问题

400错误的核心原因是文件上传错误使用了JSON格式传递数据,Razor Pages页面处理器无法解析JSON格式的文件流,必须使用multipart/form-data格式。

修改后的前端代码:

$('#fileInput').change(function () {
    var token = $('#__RequestVerificationToken').val();
    var file = this.files[0];

    if (file) {
        var reader = new FileReader();
        reader.onload = function (e) {
            $('#previewImage').attr('src', e.target.result).show();

            // 直接构建FormData,包含文件和防伪令牌
            var formData = new FormData();
            formData.append('file', file);
            formData.append('__RequestVerificationToken', token);

            $.ajax({
                type: "POST",
                url: "", // 指向当前页面
                processData: false, // 禁止jQuery自动处理FormData
                contentType: false, // 让浏览器自动设置multipart/form-data及boundary
                data: formData,
                success: function (response) {
                    console.log('File uploaded successfully');
                },
                error: function (xhr, status, error) {
                    console.error('Error uploading file:', error);
                }
            });
        };
        // 必须调用readAsDataURL才会触发reader.onload
        reader.readAsDataURL(file);
    }
});

2. 优化后端代码(可选但更规范)

恢复使用模型绑定,并确保上传目录存在:
首先定义ImageUpload类:

public class ImageUpload
{
    public IFormFile File { get; set; }
}

修改后端方法:

public async Task<IActionResult> OnPostAsync([FromForm] ImageUpload imageUpload)
{
    // 校验文件是否存在
    if (imageUpload.File == null || imageUpload.File.Length == 0)
    {
        return BadRequest("未选择上传文件");
    }

    var uploadsDir = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads");
    // 确保上传目录存在,避免文件写入失败
    if (!Directory.Exists(uploadsDir))
    {
        Directory.CreateDirectory(uploadsDir);
    }

    var fileName = Path.GetFileName(imageUpload.File.FileName);
    var filePath = Path.Combine(uploadsDir, fileName);

    using (var fileStream = new FileStream(filePath, FileMode.Create))
    {
        await imageUpload.File.CopyToAsync(fileStream);
    }

    return Content($"文件 '{fileName}' 上传成功");
}

3. 防伪令牌验证确认

Razor Pages默认自动验证POST请求的防伪令牌,只需确保:

  • 令牌名称为__RequestVerificationToken(与@Html.AntiForgeryToken()生成的一致);
  • 令牌通过FormData传递(而非请求头,避免配置冲突)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:50:39