web-dev-qa-db-ja.com

リクエスト本文を2回読み取る

認証の目的でミドルウェアでボディを読み取ろうとしていますが、リクエストが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 );
20
Jake Rote

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

_Microsoft.AspNet.Http_パッケージの一部であるBufferingHelper.EnableRewind()拡張機能を使用することもできます。これは、同様のアプローチに基づいていますが、メモリへのデータのバッファリングを開始し、すべてをtempにスプールする特別なストリームに依存していますしきい値に達したときのディスク上のファイル:

_app.Use(next => context => {
    context.Request.EnableRewind();

    return next(context);
});
_

参考までに:バッファリングミドルウェアは、おそらくvNextに追加される予定です。

31
Pinpoint

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();
    ...
    }
8
Nathan Zaetta

これは.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バージョンの一部として追加されたようです。

これが誰かを助けることを願っています!

乾杯と幸せなコーディング。

0
DasSoftware