Чтение потока Response.Body в фильтре - PullRequest
0 голосов
/ 17 октября 2018

Я пишу свой фильтр, который запускается после вызова метода sever, и печатаю его содержимое в Консоль.Код написан на ядре ASP.NET v2.1:

public class MyCustomFilter : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext context)
    {

        // ERROR on the next line!
        using (StreamReader sr = new StreamReader(context.HttpContext.Response.Body))
        {
            Console.WriteLine(sr.ReadToEnd());
        }

        base.OnResultExecuted(context);
    }
}

Результат - исключение:

Поток не читается.

Дальнейшее исследование приводит меня к выводу, что поток (context.HttpContext.Response) имеет следующие значения:

  1. CanRead = false
  2. CanSeek = false

Томогу объяснить, почему не может прочитать тело ...

Как решить?

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Не уверен, зачем тебе это нужно.context.Result - это экземпляр IActionResult, вы можете манипулировать им как хотите.Если вы действительно хотите прочитать Response.Body, можно сделать что-то хакерское.

Поскольку значение по умолчанию Response.Body не является читаемым Stream, чтобы сделать тело читаемым, мынеобходимо перехватить ответ, а именно заменить Body нашим собственным экземпляром Stream:

  1. Мы можем динамически создать новый поток памяти перед выполнением действия и перехватитьпо умолчанию Response.Body поток.
  2. Когда действие выполнено, прочитайте поток, используя StreamReader, сделайте некоторую работу и установите Response.Body=your new stream.

Безопасно угнать Response.Body простымпоток памяти, потому что тип Body является простым Stream.

public class MyCustomFilter : ActionFilterAttribute
{
    private MemoryStream responseBody ;

    public override void OnActionExecuting(ActionExecutingContext context){
        this.responseBody=new MemoryStream();
        // hijack the real stream with our own memory stream 
        context.HttpContext.Response.Body = responseBody;
    }

    public override void OnResultExecuted(ResultExecutedContext context)
    {

        responseBody.Seek(0, SeekOrigin.Begin);

        // read our own memory stream 
        using (StreamReader sr = new StreamReader(responseBody))
        {
            var actionResult= sr.ReadToEnd();
            Console.WriteLine(actionResult);
            // create new stream and assign it to body 
            // context.HttpContext.Response.Body = ;
        }

        // no ERROR on the next line!

        base.OnResultExecuted(context);
    }
}

Для целей тестирования я создаю метод действия:

[MyCustomFilter]
public IActionResult Index()
{
    return Ok("it wooooooooorks");
}

enter image description here

0 голосов
/ 17 октября 2018

Все зависит от того, чего вы хотите достичь.Если вы хотите получить значения ответа или просто просмотреть результат, вы можете использовать

context.Result or context.Result.Value

Если вы хотите изменить ответ или просто зарегистрировать весь ответ, вы должны использовать промежуточное ПО.

вот хороший пример https://exceptionnotfound.net/using-middleware-to-log-requests-and-responses-in-asp-net-core/

надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...