Читать тело запроса дважды
Я пытаюсь прочитать тело в промежуточном программном обеспечении для целей аутентификации, но когда запрос попадает в контроллер API, объект становится пустым, так как тело уже прочитано. Есть ли в любом случае вокруг этого. Я читаю тело как это в моем промежуточном программном обеспечении.
var buffer = new byte[ Convert.ToInt32( context.Request.ContentLength ) ];
await context.Request.Body.ReadAsync( buffer, 0, buffer.Length );
var body = Encoding.UTF8.GetString( buffer );
2 ответа
Если вы используете application/x-www-form-urlencoded
или же multipart/form-data
Можете смело звонить context.Request.ReadFormAsync()
несколько раз, поскольку он возвращает кэшированный экземпляр при последующих вызовах.
Если вы используете другой тип контента, вам придется вручную буферизовать запрос и заменить тело запроса перематываемым потоком, таким как MemoryStream
, Вот как вы можете это сделать, используя встроенное промежуточное программное обеспечение (вам нужно скоро зарегистрировать его в своем конвейере):
app.Use(next => async context => {
// Keep the original stream in a separate
// variable to restore it later if necessary.
var stream = context.Request.Body;
// Optimization: don't buffer the request if
// there was no stream or if it is rewindable.
if (stream == Stream.Null || stream.CanSeek) {
await next(context);
return;
}
try {
using (var buffer = new MemoryStream()) {
// Copy the request stream to the memory stream.
await stream.CopyToAsync(buffer);
// Rewind the memory stream.
buffer.Position = 0L;
// Replace the request stream by the memory stream.
context.Request.Body = buffer;
// Invoke the rest of the pipeline.
await next(context);
}
}
finally {
// Restore the original stream.
context.Request.Body = stream;
}
});
Вы также можете использовать BufferingHelper.EnableRewind()
расширение, которое является частью Microsoft.AspNet.Http
пакет: он основан на аналогичном подходе, но опирается на специальный поток, который начинает буферизацию данных в памяти и помещает все в временный файл на диске при достижении порога:
app.Use(next => context => {
context.Request.EnableRewind();
return next(context);
});
К вашему сведению: промежуточное программное обеспечение для буферизации, вероятно, будет добавлено в vNext в будущем.
Использование для упоминания PinPoint о EnableRewind
Startup.cs
using Microsoft.AspNetCore.Http.Internal;
Startup.Configure(...){
...
//Its important the rewind us added before UseMvc
app.Use(next => context => { context.Request.EnableRewind(); return next(context); });
app.UseMvc()
...
}
Затем в промежуточном программном обеспечении вы просто перематываете и перечитываете
private async Task GenerateToken(HttpContext context)
{
context.Request.EnableRewind();
string jsonData = new StreamReader(context.Request.Body).ReadToEnd();
...
}
Это работает с.Net Core 2.1 и выше.
Сегодня столкнулся с похожей проблемой. Короче говоря, с чем раньше работали
Body.Seek(0, SeekOrigin.Begin);
привело к сегодняшнему исключению, по крайней мере, в моем случае. Это произошло после того, как код был перенесен на последнюю версию.NET Core.
Обходной путь для меня заключался в том, чтобы добавить это:
app.Use(next => context => { context.Request.EnableBuffering(); return next(context);
Добавьте это перед настройкой контроллеров или MVC. Кажется, это добавлено как часть версии.NET Core 2.1.
Надеюсь, это кому-то поможет!
Ура и счастливого кодирования.