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

创建双控制器单中间件的.NET Core应用及排查POST请求400错误

问题诊断与解决

核心问题原因

你的中间件代码存在两个关键问题,直接触发了400错误:

  • 异步方法未等待:reader.ReadToEndAsync().ToString()没有使用await关键字,导致requestBody存储的是Task<string>对象的字符串表示,而非实际的请求JSON内容。这不仅让存储的数据无效,还会耗尽请求体流。
  • 请求体流未重置:即便正确读取了请求体,你没有重置流的起始位置,后续MVC控制器的模型绑定无法再次读取请求体,进而触发验证错误。

修复后的中间件代码

将Invoke方法改为异步模式,并正确处理请求体流:

public async Task Invoke(HttpContext context)
{
    if (context.Request.Method == "POST" && context.Request.ContentType?.Contains("application/json") == true)
    {
        // 启用请求体缓冲,允许后续重复读取
        context.Request.EnableBuffering();
        
        string requestBody;
        using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8, leaveOpen: true))
        {
            requestBody = await reader.ReadToEndAsync();
            // 重置流位置到起始点,保证控制器能读取
            context.Request.Body.Position = 0;
        }

        SaveToJsonFile(requestBody);
    }

    await _next(context);
}

private void SaveToJsonFile(string data)
{
    try
    {
        List<object> existingData = new List<object>();

        if (File.Exists(filePath))
        {
            var jsonData = File.ReadAllText(filePath);
            existingData = JsonConvert.DeserializeObject<List<object>>(jsonData);
        }

        var newData = JsonConvert.DeserializeObject<object>(data);
        existingData.Add(newData);

        File.WriteAllText(filePath, JsonConvert.SerializeObject(existingData, Formatting.Indented));
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error saving data: " + ex.Message);
    }
}

额外优化建议

  • 确保filePath是提前初始化的有效路径,避免因路径异常导致隐性错误。
  • 生产环境中建议给文件写入操作添加并发锁,防止多请求同时写入引发文件冲突。
  • 增加日志记录逻辑,便于后续快速排查类似流处理或数据存储问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:43:13