web-dev-qa-db-ja.com

応答ContentTypeを設定するミドルウェア

ASP.NET CoreベースのWebアプリケーションでは、次のものが必要です。要求された特定のファイルタイプは、応答としてカスタムContentTypeを取得する必要があります。例えば。 .mapapplication/jsonにマップする必要があります。 「完全な」ASP.NET4.xで、IIS)と組み合わせて、これにweb.config <staticContent>/<mimeMap>を利用することができました。この動作を、カスタムASPに置き換えたいと思います。 .NETCoreミドルウェア。

だから私は以下を試しました(簡潔にするために簡略化):

public async Task Invoke(HttpContext context)
{
    await nextMiddleware.Invoke(context);

    if (context.Response.StatusCode == (int)HttpStatusCode.OK)
    {
        if (context.Request.Path.Value.EndsWith(".map"))
        {
            context.Response.ContentType = "application/json";
        }
    }
}

残念ながら、ミドルウェアチェーンの残りの部分を呼び出した後にcontext.Response.ContentTypeを設定しようとすると、次の例外が発生します。

System.InvalidOperationException: "Headers are read-only, response has already started."

この要件を解決するミドルウェアを作成するにはどうすればよいですか?

16
Matthias

HttpContext.Response.OnStartingコールバックを使用してみてください。これは、ヘッダーが送信される前に発生する最後のイベントです。

public async Task Invoke(HttpContext context)
{
    context.Response.OnStarting((state) =>
    {
        if (context.Response.StatusCode == (int)HttpStatusCode.OK)
        {
           if (context.Request.Path.Value.EndsWith(".map"))
           {
             context.Response.ContentType = "application/json";
           }
        }          
        return Task.FromResult(0);
    }, null);

    await nextMiddleware.Invoke(context);
}
11
Set

OnStartingメソッドのオーバーロードを使用する:

public async Task Invoke(HttpContext context)
{
    context.Response.OnStarting(() =>
    {
        if (context.Response.StatusCode == (int) HttpStatusCode.OK &&
            context.Request.Path.Value.EndsWith(".map"))
        {
            context.Response.ContentType = "application/json";
        }

        return Task.CompletedTask;
    });

    await nextMiddleware.Invoke(context);
}
4
Andriy Tolstoy