我有一个asp.net核心web api项目,我在其中创建了一个动作过滤器来记录对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);
}
}
在大多数情况下,这段代码可以正常工作。当我的控制器方法使用CreatedAtAction
方法返回201代码时,我遇到了问题
return CreatedAtAction("Get", new { Id= myObject.Id });
问题是,当我点击创建对象的控制器方法时,它会在我的actionfilter中第一次进入并正确记录请求。然后,当到达返回行时,它再次击中我的actionfilter(我不确定为什么发送第二个请求,我猜它有点像重定向一样)。第二次执行actionFilter的OnActionExecuting
时,这行代码会引发异常
request.Body.Position = 0;
“无法访问已处置的对象。”
处理我的请求的正文。我的ActionFilter在Startup.cs
文件中以这种方式注册
services.AddMvc(c =>
{
c.Filters.Add(typeof(RequestLoggerActionFilter));
}
);
我的actionFilter的生命周期是Scoped,我也试过Transient,但它没有解决问题。
services.AddScoped<RequestLoggerActionFilter>();
我用request.EnableRewind();
和下面的代码进行了测试,它与CreatedAtAction
一起使用。
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.EnableRewind();
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);
}
}