2
votes

I'm trying to integrate application insights to .net core MVC application. Everything worked as expected till I added a telemetry initializer to read request body content. I created a ITelemetryInitializer which reads the content from the request body if the telemetry type is request telemetry. But i'm getting "System.ObjectDisposedException: 'Cannot access a disposed object.'"

Issue:

On debugging I noticed, when a POST/PUT http call is made, MVC action method is invoked before Initialize() method. So by the time the Initialize() method is invoked, request body request stream is already disposed. I've a similar implementation for 4.6 framework web api application, but its works fine without this issue.

Is there a way I can invoke the initializers before MVC action is executed. I tried configuring application insights with IWebHostBuilder and IServiceCollection.

Did anyone come across this issue?

Version Info SDK Version : 2.2.1 .NET Version : .Net core 2.0 How Application was onboarded with SDK(VisualStudio/StatusMonitor/Azure Extension) : OS : Hosting Info (IIS/Azure WebApps/ etc) : IIS

Update (copied code from comment):

if (!(telemetry is RequestTelemetry requestTelemetry))
   return;
var request = _httpContextAccessor.HttpContext?.Request;
if (request == null)
   return;
if (request.Body.CanRead)
{
   request.EnableRewind();
   using (var memoryStream = new MemoryStream())
   { 
      request.Body.CopyTo(memoryStream);
      request.Body.Position = 0; //add to telemetry properties
   }
}
1
Can you post the code of the Telemetry Initializer?Peter Bons
To re-read the request body you need to "EnableBuffering" devblogs.microsoft.com/aspnet/…Aaron Hoffman

1 Answers

3
votes

I replied to your post in Github as well. Here's the correct way of enriching telemetry with information from Http Post/Put request body. This is a controller Post Action, and the RequestTelemetry is enriched with information from the post body.

[HttpPost]
        public IActionResult Create([FromBody] TodoItem item)
        {
            if (item == null)
            {
                return BadRequest();
            }

            RequestTelemetry requestTelemetry = HttpContext.Features.Get<RequestTelemetry>();
            requestTelemetry.Properties.Add("nameFromBody", item.Name);

            _context.TodoItems.Add(item);
            _context.SaveChanges();

            return CreatedAtRoute("GetTodo", new { id = item.Id }, item);
        }