web-dev-qa-db-ja.com

IMiddlewareの使用時にカスタムミドルウェアの追加が機能しない

カスタムミドルウェアをパイプラインに追加しようとしています(簡単にするために、.NET Coreドキュメントの例を取り上げます)。 APIの呼び出しが発生するたびにスペインのカルチャーを設定したいとします。完全に実行されるコードは次のとおりです。

public class RequestCultureMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context)
    {
        CultureInfo.CurrentCulture = new CultureInfo("es-ES");
        CultureInfo.CurrentUICulture = new CultureInfo("es-ES");

        // Call the next delegate/middleware in the pipeline
        await _next(context);
    }
}

public static class RequestCultureMiddlewareExtensions
{
    public static IApplicationBuilder UseRequestCulture(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<RequestCultureMiddleware>();
    }
}

スタートアップクラス:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        //here is our custom middleware!
        app.UseRequestCulture();

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

それは問題ありませんが、ご覧のとおり、RequestCultureMiddlewareはインターフェイスまたは基本クラス/抽象クラスを実装していません。次のミドルウェアを受け取るコンストラクターを作成するためにミドルウェアを定義するときに覚えておく必要があるだけでなく、パラメーターとして「HttpContext」を使用して「InvokeAsync」と呼ばれるメソッドを作成する必要もあります。

コントラクトを検索しようとしました...基本クラスまたはインターフェイスと、何を推測しているのでしょうか。「Microsoft.AspNetCore.Http」アセンブリの一部である「IMiddleware」があります。うわー、それは完璧です。実装しましょう。

インターフェイスは次のようになります。

namespace Microsoft.AspNetCore.Http
{
    //
    // Summary:
    //     Defines middleware that can be added to the application's request pipeline.
    public interface IMiddleware
    {
        //
        // Summary:
        //     Request handling method.
        //
        // Parameters:
        //   context:
        //     The Microsoft.AspNetCore.Http.HttpContext for the current request.
        //
        //   next:
        //     The delegate representing the remaining middleware in the request pipeline.
        //
        // Returns:
        //     A System.Threading.Tasks.Task that represents the execution of this middleware.
        Task InvokeAsync(HttpContext context, RequestDelegate next);
    }
}

そしてここに実装があります:

    public class RequestCultureMiddleware : IMiddleware
    {

        public Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            CultureInfo.CurrentCulture = new CultureInfo("es-ES");
            CultureInfo.CurrentUICulture = new CultureInfo("es-ES");

            // Call the next delegate/middleware in the pipeline
            return next(context);
        }
    }


    public static class RequestCultureMiddlewareExtensions
    {
        public static IApplicationBuilder UseRequestCulture(
            this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<RequestCultureMiddleware>();
        }
    }
}

しかし、APIを実行すると、実行時に次のエラーが発生します。

System.InvalidOperationException: No service for type 'WebApplication1.RequestCultureMiddleware' has been registered.
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.AspNetCore.Http.MiddlewareFactory.Create(Type middlewareType)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass5_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

拡張機能「UseMiddleware」を使用しない場合、このミドルウェアを正確に登録するにはどうすればよいですか?ありがとう。

7
Dragos Stoica

この問題は5か月後にはかなり前に解決されたと思いますが、念のためこのアドバイスを書いています。

問題は、カスタムミドルウェアプログラムの「InvokeAsync」メソッドが、スタートアップの「構成」メソッドに組み込まれているにもかかわらず実行されないことです。

先日同じ問題が発生して解決しましたが、組み込みコードをapp.UseEndpointsメソッドの直前に配置しました。

あなたの場合

app.UseAuthorization();
app.UseRequestCulture();  // <- this way.
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

ちなみに、app.UseEndpointsメソッドの後に置くと、コンストラクターが呼び出されますが、InvokeAsyncメソッドは実行されません。

0