.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
相关产品推荐
相关产品推荐

