Запрос чтенияBody прерывает поток в ASP. NET Core 2.2 шлюзе - PullRequest
0 голосов
/ 17 января 2020

У меня есть промежуточное ПО для отслеживания производительности моего специально разработанного шлюза в ASP. NET Core 2.2 API. Я использовал этот пост от StackOverflow.

В основном основная часть выглядит следующим образом:

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;
        /* MY CODE COMES HERE */

        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;
        }

    } 

Этот код работает нормально. Но я хочу записать вход (тело JSON) на шлюз и добавить следующие строки:

using (System.IO.StreamReader rd = new System.IO.StreamReader(context.Request.Body))
{
    bodyStr = rd.ReadToEnd();
}

Это читает тело ввода из запроса, но поток прерывается, а остальная часть процесс не выполняется, что приводит к «внутренней ошибке сервера HTTP 500». Я предполагаю, что чтение тела запроса через поток что-то нарушает.

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

1 Ответ

1 голос
/ 17 января 2020

Идея состоит в том, чтобы вызвать EnableBuffering для включения многократного чтения, а затем не удалять тело запроса после того, как вы закончили его чтение. Следующее работает для меня.

// Enable the request body to be read in the future
context.Request.EnableBuffering();

// Read the request body, but do not dispose it
var stream = new StreamReader(context.Request.Body);            
string requestBody = await stream.ReadToEndAsync();

// Reset to the origin so the next read would start from the beginning
context.Request.Body.Seek(0, SeekOrigin.Begin);
...