Как читать ASP.NET Core Response.Body?

JTW:

Я изо всех сил пытался получить Response.Bodyсвойство из действия ASP.NET Core, и единственное решение, которое я смог определить, кажется неоптимальным. Решение требует замены из Response.Bodyс MemoryStreamпри чтении потока в строковую переменную, а затем обменивать его обратно перед отправкой клиенту. В приведенных ниже примерах я пытаюсь получить Response.Bodyзначение в настраиваемом классе промежуточного программного обеспечения. по какой-то причине Response.Bodyявляется свойством только для набора в ASP.NET Core? Я просто что-то упустил или это проблема недосмотра / ошибки / дизайна? Есть ли лучший способ читать Response.Body?

Текущее (неоптимальное) решение:

public class MyMiddleWare
{
    private readonly RequestDelegate _next;

    public MyMiddleWare(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        using (var swapStream = new MemoryStream())
        {
            var originalResponseBody = context.Response.Body;

            context.Response.Body = swapStream;

            await _next(context);

            swapStream.Seek(0, SeekOrigin.Begin);
            string responseBody = new StreamReader(swapStream).ReadToEnd();
            swapStream.Seek(0, SeekOrigin.Begin);

            await swapStream.CopyToAsync(originalResponseBody);
            context.Response.Body = originalResponseBody;
        }
    }
}  

Попытка решения с использованием EnableRewind (): работает только для Request.Body, но не для Response.Body. Это приводит к чтению пустой строки, Response.Bodyа не фактического содержимого тела ответа.

Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifeTime)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.Use(async (context, next) => {
        context.Request.EnableRewind();
        await next();
    });

    app.UseMyMiddleWare();

    app.UseMvc();

    // Dispose of Autofac container on application stop
    appLifeTime.ApplicationStopped.Register(() => this.ApplicationContainer.Dispose());
}

MyMiddleWare.cs

public class MyMiddleWare
{
    private readonly RequestDelegate _next;

    public MyMiddleWare(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        await _next(context);
        string responseBody = new StreamReader(context.Request.Body).ReadToEnd(); //responseBody is ""
        context.Request.Body.Position = 0;
    }
}  
Рон С:

В моем первоначальном ответе я совершенно неправильно понял вопрос и подумал, что плакат спрашивает, как читать. Request.BodyНо он спросил, как читать Response.Body. Я оставляю свой исходный ответ, чтобы сохранить историю, но также обновляю его, чтобы показать, как я отвечу на вопрос, прочитав его правильно.

Оригинальный ответ

Если вам нужен буферизованный поток, поддерживающий многократное чтение, вам нужно установить

   context.Request.EnableRewind()

В идеале это нужно делать на раннем этапе промежуточного программного обеспечения, прежде чем что-либо понадобится для чтения тела.

Так, например, вы можете поместить следующий код в начало Configureметода файла Startup.cs:

        app.Use(async (context, next) => {
            context.Request.EnableRewind();
            await next();
        });

Перед включением перемотки назад поток, связанный с, Request.Bodyявляется потоком только вперед, который не поддерживает поиск или чтение потока во второй раз. Это было сделано для того, чтобы сделать стандартную конфигурацию обработки запросов как можно более легкой и производительной. Но как только вы включаете перемотку назад, поток обновляется до потока, который поддерживает поиск и чтение несколько раз. Вы можете наблюдать это «обновление», установив точку останова непосредственно перед и сразу после вызова EnableRewindи наблюдая за Request.Bodyсвойствами. Так, например Request.Body.CanSeek, изменится с falseна true.

обновление : Request.EnableBuffering()доступен запуск в ASP.NET Core 2.1, который обновляет его Request.Bodyдо FileBufferingReadStreamподобного, Request.EnableRewind()и, поскольку он Request.EnableBuffering()находится в общедоступном пространстве имен, а не во внутреннем, его следует предпочесть EnableRewind (). (Спасибо @ArjanEinbu за указание)

Затем, чтобы прочитать поток тела, вы могли бы, например, сделать это:

   string bodyContent = new StreamReader(Request.Body).ReadToEnd();

Не оборачивайте StreamReaderсоздание в операторе using, иначе он закроет базовый поток тела по завершении блока using, и код позже в жизненном цикле запроса не сможет прочитать тело.

Также на всякий случай было бы неплохо выполнить приведенную выше строку кода, которая считывает содержимое тела, с этой строкой кода, чтобы сбросить позицию потока тела обратно на 0.

request.Body.Position = 0;

Таким образом, любой код позже в жизненном цикле запроса найдет request.Body в таком состоянии, как если бы он еще не был прочитан.

Обновленный ответ

Извините, я неправильно понял ваш вопрос. По-прежнему применяется концепция обновления связанного потока до буферизованного потока. Однако вам нужно делать это вручную, мне неизвестны какие-либо встроенные функции .Net Core, которые позволяют вам читать поток ответов, однажды записанный таким образом, чтобы EnableRewind()разработчик мог повторно прочитать поток запроса после того, как он был прочитан.

Ваш "хакерский" подход, вероятно, полностью уместен. Вы в основном конвертируете поток, который не может искать, в поток, который может. В конце дня Response.Bodyпоток должен быть заменен потоком, который буферизирован и поддерживает поиск. Вот еще один подход к промежуточному программному обеспечению, но вы заметите, что он очень похож на ваш подход. Однако я решил использовать блок finally в качестве дополнительной защиты для возврата исходного потока обратно в, Response.Bodyи я использовал Positionсвойство потока, а не Seekметод, поскольку синтаксис немного проще, но эффект не отличается от вашего подхода.

public class ResponseRewindMiddleware 
{
        private readonly RequestDelegate next;

        public ResponseRewindMiddleware(RequestDelegate next) {
            this.next = next;
        }

        public async Task Invoke(HttpContext context) {

            Stream originalBody = context.Response.Body;

            try {
                using (var memStream = new MemoryStream()) {
                    context.Response.Body = memStream;

                    await next(context);

                    memStream.Position = 0;
                    string responseBody = new StreamReader(memStream).ReadToEnd();

                    memStream.Position = 0;
                    await memStream.CopyToAsync(originalBody);
                }

            } finally {
                context.Response.Body = originalBody;
            }

        } 
}

Эта статья взята из Интернета, укажите источник при перепечатке.

Если есть какие-либо нарушения, пожалуйста, свяжитесь с[email protected] Удалить.

Отредактировано в
0

я говорю два предложения

0обзор
Войти в системуУчаствуйте в комментариях

Статьи по теме

Как сбросить Asp.Net Core Response.Body после записи некоторых данных

Как изменить код состояния http после начала записи в поток HttpContext.Response.Body в ASP.NET Core?

How to log the HTTP Response Body in ASP.NET Core 1.0

Контроллер API ASP.NET Core: строка Response.Body.WriteAsync base64 не работает

Как определить, когда клиент закрыл поток при записи в Response.Body в ядре asp.net

Как документально оформить действие ASP.NET Core, которое напрямую читает Request.Body

неопределенная ошибка во время выполнения при использовании response-redux вместе с ASP.NET Core

Обработка ошибок ASP.Net Core 2: как вернуть подробные сведения об исключении в формате Http Response?

Asp.Net Core ControllerBase.Response, где исходный код?

Как HttpContext RESPONSE END в ASP.NET Core

Retrieve http response body from .net core API in angular 7

Setting Body of caught error in Middleware asp.net core 2

Asp Net Core Web Api POST Request.Body всегда длина 0

asp.net core 1.0 mvc. Получите необработанный контент из Request.Body

Чтение необработанного Request.Body в действии MVC Asp.Net Core с параметрами маршрута

Шаблон и удостоверение ASP.NET Core 2.1 MVC response.js

Control Guid format in ASP.NET Core action's response

Использование нового сериализатора Json с HttpContext.Response в ASP.NET Core 3.1

Есть ли эквивалент Response.Redirect ("~ / Controller /") в Asp.Net Core 2?

Как Response.Cookies.Append () в ASP.Net Core 1.1?

Как Response.Cookies.Append () в ASP.Net Core 1.1?

ASP.Net Core parse Stripe Webhook JSON Response

Есть ли эквивалент «HttpContext.Response.Write» в Asp.Net Core 2?

Get the compressed response length in ASP.net Core

ASP.Net Core parse Stripe Webhook JSON Response

в чем разница между asp .net и asp .net core?

Unable to access HTTP request body content in ASP.NET Core 3.1 exception handler

Выбор между полной платформой .NET и .NET Core в качестве целевой платформы ASP.NET Core?

Перенос классического приложения ASP на ASP.NET Core

TOP список

  1. 1

    Распределение Рэлея Curve_fit на Python

  2. 2

    Définition de la valeur par défaut dans le dictionnaire Python si la clé est manquante

  3. 3

    Невозможно отобразить данные модели загрузки Spring в Thymeleaf

  4. 4

    Merging legends in plotly subplot

  5. 5

    Spring Boot Upload Multipart 413 Request Entity Too Large

  6. 6

    Ошибка. Невозможно использовать член экземпляра xxx в инициализаторе свойства.

  7. 7

    Перебирайте несколько столбцов в фрейме данных Panda и находите уникальные значения подсчета

  8. 8

    TypeError: store.getState não é uma função. (Em 'store.getState ()', 'store.getState' é indefinido, como posso resolver esse problema?

  9. 9

    В типе Observable <unknown> отсутствуют следующие свойства из типа Promise <any>.

  10. 10

    Ошибка отладчика кода Visual Studio: «Не удалось найти задачу« gcc build active file »

  11. 11

    np.fft.ifft2 делает изображение полностью черным

  12. 12

    Использование виджетов времени / даты Django в настраиваемой форме

  13. 13

    Ошибки компоновщика в GoogleMobileVision при использовании Firebase ML Kit на iOS без кокаподов

  14. 14

    Вызов выполнения .bat в cmd из Java ничего не делает

  15. 15

    Переопределить некоторые стили класса material-ui, но сохранить стили по умолчанию

  16. 16

    Как добавить Swagger в веб-API с поддержкой OData, работающий на ASP.NET Core 3.1

  17. 17

    Как я могу нарисовать заполненный прямоугольник в JFreeChart?

  18. 18

    Сводная таблица из запроса по месяцам в TeraData

  19. 19

    Обновление строк и столбцов с помощью openpyxl из python

  20. 20

    Чтение данных по строкам в Python с использованием openpyxl

  21. 21

    Как создать переменную с использованием класса Color, который включает только выбранные цвета?

популярныйтег

файл