Reputation: 82
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
}
}
Upvotes: 2
Views: 3526
Reputation: 3126
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);
}
Upvotes: 3