阅读ActionFilterAttribute中的Asp.Net核心响应正文

阅读ActionFilterAttribute中的Asp.Net核心响应正文,asp.net,asp.net-mvc,asp.net-core,.net-core,Asp.net,Asp.net Mvc,Asp.net Core,.net Core,我正在使用Asp.NETCore作为RESTAPI服务。 我需要访问ActionFilter中的请求和响应。实际上,我在OnActionExcecuted中找到了请求,但我无法读取响应结果 我尝试按如下方式返回值: [HttpGet] [ProducesResponseType(typeof(ResponseType), (int)HttpStatusCode.OK)] [Route("[action]")] public async Task<IActionResult> Get(

我正在使用Asp.NETCore作为RESTAPI服务。 我需要访问ActionFilter中的请求和响应。实际上,我在OnActionExcecuted中找到了请求,但我无法读取响应结果

我尝试按如下方式返回值:

[HttpGet]
[ProducesResponseType(typeof(ResponseType), (int)HttpStatusCode.OK)]
[Route("[action]")]
public async Task<IActionResult> Get(CancellationToken cancellationToken)
{
    var model = await _responseServices.Get(cancellationToken);
    return Ok(model);
}
_request = context.HttpContext.Request.ReadAsString().Result;
_response = context.HttpContext.Response.ReadAsString().Result; //?
public static async Task<string> ReadAsString(this HttpResponse response)
{
     var initialBody = response.Body;
     var buffer = new byte[Convert.ToInt32(response.ContentLength)];
     await response.Body.ReadAsync(buffer, 0, buffer.Length);
     var body = Encoding.UTF8.GetString(buffer);
     response.Body = initialBody;
     return body;
 }
我试图在ReadAsString中作为扩展方法获取响应,如下所示:

[HttpGet]
[ProducesResponseType(typeof(ResponseType), (int)HttpStatusCode.OK)]
[Route("[action]")]
public async Task<IActionResult> Get(CancellationToken cancellationToken)
{
    var model = await _responseServices.Get(cancellationToken);
    return Ok(model);
}
_request = context.HttpContext.Request.ReadAsString().Result;
_response = context.HttpContext.Response.ReadAsString().Result; //?
public static async Task<string> ReadAsString(this HttpResponse response)
{
     var initialBody = response.Body;
     var buffer = new byte[Convert.ToInt32(response.ContentLength)];
     await response.Body.ReadAsync(buffer, 0, buffer.Length);
     var body = Encoding.UTF8.GetString(buffer);
     response.Body = initialBody;
     return body;
 }
公共静态异步任务ReadAsString(此HttpResponse响应)
{
var initialBody=response.Body;
var buffer=新字节[Convert.ToInt32(response.ContentLength)];
wait response.Body.ReadAsync(buffer,0,buffer.Length);
var body=Encoding.UTF8.GetString(缓冲区);
response.Body=initialBody;
返回体;
}
但是,没有结果

如何在OnActionExcecuted中获得响应


感谢大家花时间尝试并帮助解释

如果您正在记录json结果/查看结果,您不需要阅读整个响应流。只需序列化
上下文。结果

public class MyFilterAttribute : ActionFilterAttribute
{
    private ILogger<MyFilterAttribute> logger;

    public MyFilterAttribute(ILogger<MyFilterAttribute> logger){
        this.logger = logger;
    }
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        var result = context.Result;
        if (result is JsonResult json)
        {
            var x = json.Value;
            var status = json.StatusCode;
            this.logger.LogInformation(JsonConvert.SerializeObject(x));
        }
        if(result is ViewResult view){
            // I think it's better to log ViewData instead of the finally rendered template string
            var status = view.StatusCode;
            var x = view.ViewData;
            var name = view.ViewName;
            this.logger.LogInformation(JsonConvert.SerializeObject(x));
        }
        else{
            this.logger.LogInformation("...");
        }
    }
公共类MyFilterAttribute:ActionFilterAttribute
{
私人ILogger记录器;
公共MyFilterAttribute(ILogger记录器){
this.logger=记录器;
}
公共覆盖无效OnActionExecuted(ActionExecutedContext上下文)
{
var result=context.result;
if(结果为JsonResult json)
{
var x=json.Value;
var status=json.StatusCode;
this.logger.LogInformation(JsonConvert.SerializeObject(x));
}
如果(结果是视图结果视图){
//我认为最好记录ViewData,而不是最终呈现的模板字符串
var status=view.StatusCode;
var x=view.ViewData;
var name=view.ViewName;
this.logger.LogInformation(JsonConvert.SerializeObject(x));
}
否则{
this.logger.LogInformation(“…”);
}
}

我知道已经有了答案,但我还想补充一点,问题是MVC管道在运行
ActionFilter
时没有填充
响应.Body
,因此您无法访问它。
响应.Body
由MVC
中间件填充

如果要阅读
Response.Body
,则需要创建自己的自定义中间件,以便在填充响应对象时拦截调用。有许多网站可以向您展示如何执行此操作。例如

正如在另一个答案中所讨论的,如果您想在
ActionFilter
中执行此操作,您可以使用
上下文.Result
来访问信息。

您也可以执行以下操作

string response = "Hello";
if (result is ObjectResult objectResult)
        {
            var status = objectResult.StatusCode;
            var value = objectResult.Value;
            var stringResult = objectResult.ToString();
            responce = (JsonConvert.SerializeObject(value));
        }
我在一个.net核心应用程序中使用了这个


希望对您有所帮助。

对于ASP.NET核心过滤器管道中记录整个请求和响应,您可以使用

在Startup.cs中添加

    app.UseMiddleware<ResponseRewindMiddleware>();

    services.AddScoped<LogRequestResponseAttribute>();

你可以从感谢中得到想法,我尝试了很多方法,但所有主题都没有得到回应。你为什么要阅读回应?虽然阅读回应是可能的,但如果你告诉我们你的意图,也许有更好的方法来实现你的目标。这可能有助于你我需要知道哪些数据提供给client并将所有结果记录为JSON@itminus。这个答案比我见过的其他常见解决方案要高效得多(不管怎样,在代码方面),这些解决方案似乎普遍建议替换和跟踪
响应。Body
的内存流!谢谢!