I have a asp.net core web api project in which I created an action filter to log every call made to the api
public class RequestLoggerActionFilter : ActionFilterAttribute
{
private readonly ILogger _logger;
public RequestLoggerActionFilter(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger("RequestLogger");
}
public override void OnActionExecuting(ActionExecutingContext context)
{
var request = context.HttpContext.Request;
request.Body.Position = 0;
using (var reader = new StreamReader(request.Body))
{
var bodyString = reader.ReadToEnd();
_logger.LogInformation($"API call recevied on {request.Method.ToUpper()} {request.Path} RequestBody: {bodyString}");
}
base.OnActionExecuting(context);
}
}
This piece of code works ok in most case. I get problem when my controller method return a 201 code using CreatedAtAction method
return CreatedAtAction("Get", new { Id= myObject.Id });
the problem is, when I hit my controller method which creates an object, it enters a first time in my actionfilter and logs the request correctly. Then, when the return line is reached , it hits my actionfilter a second time (I'm not sure why a second request is send, I guess it's kind of doing the same thing as a Redirect). The second time OnActionExecuting of my actionFilter is executed, this line of code throws an exception
request.Body.Position = 0;
'Cannot access a disposed object.'
Body of my request is disposed. My ActionFilter is registered this way in Startup.cs file
services.AddMvc(c =>
{
c.Filters.Add(typeof(RequestLoggerActionFilter));
}
);
The lifecycle of my actionFilter is Scoped, I also tried Transient, but it doesn't fix the problem.
services.AddScoped<RequestLoggerActionFilter>();