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

.NET 7 MVC中间件多图片请求返回异常求助

问题分析与解决方案

问题原因

  • .NET中间件默认采用单例模式,AlbumMiddleware类中的RequstPathFull是实例级公共字段,多个并发请求会共享同一个中间件实例,导致后续请求的路径覆盖之前请求的路径。
  • 当页面同时请求多张图片时,多个请求的ValidateRequest方法会交替修改RequstPathFull的值,最终Invoke方法调用SendFileAsync时,使用的是最后一次被修改的路径,因此大多返回最后一张图片。
  • 日志记录混乱也是因为并发场景下RequstPathFull被频繁覆盖,导致日志输出的不是当前请求的实际路径。

解决方案

核心思路是禁止在中间件实例中存储请求级别的数据,将请求相关变量改为局部变量,确保每个请求的数据独立不共享。

修改后的AlbumMiddleware代码

public class AlbumMiddleware {
    protected TConfig _config = null;
    protected string _webRootPath = "";
    protected MyRepository _db = null;
    public string Ext { get; set; } = "";   // .jpg or .zip

    public AlbumMiddleware(RequestDelegate next, IOptions<AlbumMiddlewareOptions> option, IConfiguration configuration, IWebHostEnvironment webHostEnvironment, MyRepository repository)
    {
        _config = configuration.GetSection("SiteSettings").Get<TConfig>();
        _webRootPath = webHostEnvironment.WebRootPath;
        _db = repository;
        Ext = option.Value.Ext;
    }

    public async Task Invoke(HttpContext context)
    {       
        string requestPathFull = "";
        if (await ValidateRequest(context, Ext, out requestPathFull))
        {            
            await context.Response.SendFileAsync(requestPathFull);
        }
        else
        {
            string invalid = "invalid";
            await context.Response.WriteAsJsonAsync(invalid);
        }
    }

    protected async Task<bool> ValidateRequest(HttpContext context, string ext, out string requestPathFull)
    {
        string requestFile = context.Request.Path.ToString() ?? "";
        requestPathFull = $"{_webRootPath}{context.Request.PathBase}{context.Request.Path}".Replace("/", "\\");
        System.Diagnostics.Trace.WriteLine($"MW: {requestPathFull}");
        
        var itemId = 10;    // 实际逻辑从文件名提取
        var memberId = 1;   // 实际逻辑从会话获取
        if (await _db.IfMemberOwnAlbumImage(memberId, itemId))
        {
            return true;
        }
        return false;
    }
}

关键修改点

  • 移除实例字段RequstPathFull,改用局部变量存储当前请求的文件路径,避免并发覆盖。
  • 修改ValidateRequest方法,通过out参数传递当前请求的文件路径,不再依赖实例共享变量。
  • 确保每个请求的路径数据完全独立,不会被其他请求干扰。

额外建议

  • 中间件中应避免使用实例级可变字段存储请求相关数据,所有请求专属数据优先放在局部变量或HttpContext.Items中。
  • 若需在多个方法间传递请求数据,优先使用方法参数(如out/ref)或HttpContext.Items,而非实例字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:12:35