Asp.Net核心ActionFilter上下文请求正文已处理

时间:2018-09-12 16:40:27

标签: asp.net-core dependency-injection asp.net-core-webapi

我有一个asp.net核心网络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的OnActionExecuting时,此代码行引发异常

request.Body.Position = 0;
  

“无法访问已处置的对象。”

我的请求正文已被处理。我的ActionFilter以这种方式注册在Startup.cs文件中

services.AddMvc(c =>
                {
                    c.Filters.Add(typeof(RequestLoggerActionFilter));
                }
            );

我的actionFilter的生命周期是有作用域的,我也尝试过Transient,但这不能解决问题。

services.AddScoped<RequestLoggerActionFilter>();

1 个答案:

答案 0 :(得分:0)

我使用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);
    }
}