首页 > 解决方案 > StreamReader 上的 EnableRewind 和 leaveOpen 不会停止处理请求

问题描述

我正在使用 ApplicationInsights,我想将请求和响应添加到日志记录属性。

为了实现这一点,我正在实施我自己的ITelemetryInitializer. 它看起来就像这样。

    public class MyInitializer : ITelemetryInitializer
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public MyInitializer(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public void Initialize(ITelemetry telemetry)
        {
            var requestTelemetry = telemetry as RequestTelemetry;

            if (requestTelemetry == null || _httpContextAccessor?.HttpContext?.Request == null 
                || requestTelemetry.Properties.ContainsKey("RequestBody"))
            {
                return;
            }

            var request = _httpContextAccessor?.HttpContext?.Request;
            request?.EnableRewind();

            if (request.Method.Equals(HttpMethod.Post.ToString(), StringComparison.InvariantCultureIgnoreCase)
                || request.Method.Equals(HttpMethod.Put.ToString(), StringComparison.InvariantCultureIgnoreCase))
            {
                using (var reader = new StreamReader(request.Body, Encoding.UTF8, true, 1024, true))
                {
                    var requestBody = reader.ReadToEnd();
                    requestTelemetry.Properties.Add("RequestBody", requestBody);
                }
            }
        }
    }

在启动时我添加了这个

services.AddHttpContextAccessor();
services.AddSingleton<ITelemetryInitializer, MyInitializer>();
services.AddApplicationInsightsTelemetry();

我得到的错误是:

ObjectDisposedException: Cannot access a disposed object.
Object name: FileBufferingReadStream.
Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.ThrowIfDisposed()

我已经使用.EnableRewind并指示StreamReader将文件保持打开状态。尽管如此,当我的请求实际到达我的控制器时,或者甚至当它再次到达我的初始化程序以进行第二次传递(设置响应信息)时,我的请求仍然为空。

欢迎任何建议。


此外,我尝试添加一个中间件以确保.EnableRewind一切正常,但这没有任何作用。我不希望添加任何额外的中间件,因为我希望没有其他依赖项。

app.Use(async (context, next) =>
{
    context.Request.EnableRewind();
    await next();
});

谢谢。

标签: .net-core

解决方案


与往常一样,解决方案最终只是一行代码。我要感谢 Gunnar Peipman 先生的博文阅读 ASP.NET Core 中的请求正文

该行: request.Body.Seek(0, SeekOrigin.Begin);

编码

public class MyInitializer : ITelemetryInitializer
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyInitializer(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void Initialize(ITelemetry telemetry)
    {
        var requestTelemetry = telemetry as RequestTelemetry;

        if (requestTelemetry == null || _httpContextAccessor?.HttpContext?.Request == null
                                     || requestTelemetry.Properties.ContainsKey("RequestBody"))
        {
            return;
        }

        var request = _httpContextAccessor?.HttpContext?.Request;
        request?.EnableRewind();

        if (request.Method.Equals(HttpMethod.Post.ToString(), StringComparison.InvariantCultureIgnoreCase)
            || request.Method.Equals(HttpMethod.Put.ToString(), StringComparison.InvariantCultureIgnoreCase))
        {
            using (var reader = new StreamReader(request.Body, Encoding.UTF8, true, 1024, true))
            {
                var requestBody = reader.ReadToEnd();
                request.Body.Seek(0, SeekOrigin.Begin);

                requestTelemetry.Properties.Add("RequestBody", requestBody);
            }
        }
    }
}

推荐阅读