ASP.NET 核心中间件打破物理文件控制器方法

ASP.NET Core Middleware Breaks Physical File Controller Method

我使用以下中间件来替换响应内容:

app.Use(async (context, next) => {
    var body = context.Response.Body;

    using (var updatedBody = new MemoryStream()) {
        context.Response.Body = updatedBody;

        await next();

        context.Response.Body = body;

        updatedBody.Seek(0, SeekOrigin.Begin);

        var newContent = new StreamReader(updatedBody).ReadToEnd();

        // Replace content here ...

        await context.Response.WriteAsync(newContent);
    }
});

这很好用。但是现在说我有以下操作方法:

public IActionResult Image() {
    return PhysicalFile(@"C:\myimage.jpg", "image/jpeg");
}

当它尝试显示此图像时,它不会加载,但如果我删除中间件,它就会加载。

请注意我使用的是 ASP.NET Core 3.

可能是这样的:

    app.UseWhen(context => context.Response.ContentType == "text/html", subApp => subApp.Use(async (context, next) =>
    {
        var body = context.Response.Body;

        using (var updatedBody = new MemoryStream())
        {
            context.Response.Body = updatedBody;

            await next();

            context.Response.Body = body;

            updatedBody.Seek(0, SeekOrigin.Begin);

            var newContent = new StreamReader(updatedBody).ReadToEnd();

            // Replace content here ...

            await context.Response.WriteAsync(newContent);
        }
    }));

这是我想出的解决方案:

app.Use(async (context, next) => {
    var body = context.Response.Body;

    using (var updatedBody = new MemoryStream()) {
        context.Response.Body = updatedBody;

        try {
            await next();
        } catch {
            throw;
        } finally {
            context.Response.Body = body;
        }

        if (context.Response.StatusCode == 200 && context.Response.ContentType != null && context.Response.ContentType.Contains("text/html", StringComparison.InvariantCultureIgnoreCase)) {
            updatedBody.Seek(0, SeekOrigin.Begin);

            using (var reader = new StreamReader(updatedBody)) {
                var newContent = reader.ReadToEnd();

                // Replace content here

                await context.Response.WriteAsync(newContent);
            }
        } else {
            if (updatedBody.Length > 0)
                await context.Response.Body.WriteAsync(updatedBody.ToArray());
        }
    }
});

This article 感谢@CodeCaster 的建议。作为额外的奖励,我修复了一个问题,它通过在对委托的调用周围包装 try/catch 来破坏开发人员异常页面。