HttpContext.Request.Body удаляется при доступе через ApplicationInsights ITelemetryInitializer - PullRequest
1 голос
/ 20 сентября 2019

Я пытаюсь зарегистрировать POST, PUT, PATCH json тел в приложении, используя ITelemetryInitializer.Каждый раз, когда появляется сообщение, кажется, что мой поток сообщений уже избавлен от того, как.Я предполагаю, что в конвейере запросов есть что-то, что я не регистрирую / не делаю должным образом.

 public class RequestBodyLogger : ITelemetryInitializer
    {
        readonly IHttpContextAccessor httpContextAccessor;

        public RequestBodyLogger(IHttpContextAccessor httpContextAccessor)
        {
            this.httpContextAccessor = httpContextAccessor;
        }

        public void Initialize(ITelemetry telemetry)
        {
            try
            {
                if (telemetry is RequestTelemetry requestTelemetry)
                {
                    if ((httpContextAccessor.HttpContext.Request.Method == HttpMethods.Post ||
                         httpContextAccessor.HttpContext.Request.Method == HttpMethods.Put ||
                         httpContextAccessor.HttpContext.Request.Method == HttpMethods.Patch) &&
                        httpContextAccessor.HttpContext.Request.Body.CanRead)
                    {
                        const string jsonBody = "JsonBody";

                        if (requestTelemetry.Properties.ContainsKey(jsonBody))
                        {
                            return;
                        }

                        //Allows re-usage of the stream
                        httpContextAccessor.HttpContext.Request.EnableRewind();

                        var stream = new StreamReader(httpContextAccessor.HttpContext.Request.Body);
                        var body = stream.ReadToEnd(); <<Blows here object disposed (stream)

                        //Reset the stream so data is not lost
                        httpContextAccessor.HttpContext.Request.Body.Position = 0;
                        requestTelemetry.Properties.Add(jsonBody, body);
                    }
                }
            }
            catch (Exception e)
            {

            }

        }
    }

Настройка метода служб ...

        public void ConfigureServices(IServiceCollection services)
        {

            if (_env.IsDevelopment())
            {
                services.AddSwaggerGen(c =>
                {
                    c.SwaggerDoc(Constants.ApiVersion, new Info { Title = Constants.ApiName, Version = Constants.ApiVersion });
                    c.AddSecurityDefinition("Bearer", new ApiKeyScheme { In = "header", Description = "Please enter Bearer Token", Name = "Authorization", Type = "apiKey" });
                    c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> { { "Bearer", Enumerable.Empty<string>() } });
                    c.IncludeXmlComments($"{AppDomain.CurrentDomain.BaseDirectory}\\TradeJournal.Api.xml");
                });

            }


            services.AddAuthentication(options =>
                {
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                    .AddJwtBearer(options =>
                    {
                        options.Authority = Configuration["IdentityAuthority"];
                        options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                        {
                            IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
                            {
                                var json = new WebClient().DownloadString(parameters.ValidIssuer + "/.well-known/jwks.json");
                                var keys = JsonConvert.DeserializeObject<JsonWebKeySet>(json).Keys;
                                return (IEnumerable<SecurityKey>)keys;
                            },
                            ValidIssuer = Configuration["IdentityAuthority"],
                            ValidateIssuerSigningKey = true,
                            ValidateIssuer = true,
                            ValidateLifetime = true,
                            ValidateAudience = false
                        };
                    });



            services
                .AddCors(c =>
                        {
                            c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials());
                        });

            services.AddMvc(opts =>
            {
                opts.Filters.Add(typeof(ModelStateValidationFilter));

            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
            .AddJsonOptions(opt =>
            {
                opt.SerializerSettings.DateFormatString = "yyyy-MM-ddTHH:mm:ssZ";
            });
            services.AddSingleton<ITelemetryInitializer, RequestBodyLogger>();
            services.AddTransient<ExceptionToHttpResponseMiddleware>();
            services.AddTransient<MaintenanceMiddleware>();
            services.AddRouting(opts =>
            {
                opts.LowercaseUrls = true;
                opts.LowercaseQueryStrings = true;
            });

            BootstrapLayers(services);
        }
    ```  
Configure method...




     public void Configure(IApplicationBuilder app)
            {
                if (_env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                    app.UseSwagger();
                    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
                    // specifying the Swagger JSON endpoint.
                    app.UseSwaggerUI(c =>
                    {
                        c.SwaggerEndpoint($"/swagger/{Constants.ApiVersion}/swagger.json", Constants.ApiName);
                    });
                }
                else
                {
                    //The default HSTS value is 30 days.You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
                app.UseAuthentication();
                app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials());
                app.UseMiddleware<ExceptionToHttpResponseMiddleware>();
                app.UseMiddleware<MaintenanceMiddleware>();
                app.UseHttpsRedirection();
                app.UseMvc();

            }

**Why is the context disposed by the time AI calls this telemetry initializer?**


1 Ответ

1 голос
/ 25 сентября 2019

Это также обсуждается в github: https://github.com/microsoft/ApplicationInsights-aspnetcore/issues/940#issuecomment-513297006

Поскольку к моменту запуска TelemetryInitializer тело запроса будет удалено, лучше всего прочитать и заполнить тело в RequestTelemetry, когда тело ещедоступный.Если это контроллер или промежуточное программное обеспечение - тогда получите RequestTelemetry там, добавьте тело к нему.Ниже приведен пример кода, который должен быть записан в контроллере / промежуточном программном обеспечении, где вы можете получить тело запроса.

RequestTelemetry reqTelemetry = httpContext?.Features.Get<RequestTelemetry>();
reqTelemetry.Properties.Add("body","body contents").
...