使用 IMiddleware 时添加自定义中间件不起作用 [英] Adding custom middleware not working when using IMiddleware

查看:30
本文介绍了使用 IMiddleware 时添加自定义中间件不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试向管道添加自定义中间件(为了更容易,我将选择 .NET Core 文档示例).假设我们希望在调用 API 时设置西班牙文化.这是完美运行的代码:

I am trying to add a custom middleware to the pipeline (to be easier I will pick the .NET Core documentation example). Let's say we want to have the Spanish culture set whenever a call to API is fired. Here's the code which runs perfectly:

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 没有实现接口或基类/抽象类.您只需要记住在定义中间件以创建接收下一个中间件的构造函数时,您还需要创建一个专门名为InvokeAsync"的方法,并以HttpContext"为参数.

That's fine, but as you can see, the RequestCultureMiddleware does not implement an interface or a base class/abstract class. You just need to remember when defining a middleware to create a constructor that receives the next middleware and also you need to create a method called specifically "InvokeAsync" with "HttpContext" as a parameter.

我试图找到一个契约……一个基类或一个接口,猜猜是什么,我们有IMiddleware",它是Microsoft.AspNetCore.Http"程序集的一部分.哇,这太完美了.让我们实施它.

I tried to find a contract... a base class or an interface and guess what, we have "IMiddleware" which is part of "Microsoft.AspNetCore.Http" assembly. Wow, that's perfect. Let's implement it.

界面如下:

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 时,我在运行时收到以下错误:

But, when running the API I am getting the following error at run-time:

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",我应该如何注册这个中间件?谢谢.

How exactly I am supposed to register this middleware if not by using the extension "UseMiddleware"? Thanks.

推荐答案

您正在使用 基于工厂的中间件.如这些文档中所述,您错过了一个重要步骤:

You're using factory-based middleware. As described in those docs, you've missed an important step:

... IMiddlewareFactory 实例在容器中注册用于解析IMiddleware 实现而不是使用基于约定的中间件激活逻辑.中间件注册为 应用的服务容器中的>作用域或临时服务.

... the IMiddlewareFactory instance registered in the container is used to resolve the IMiddleware implementation instead of using the convention-based middleware activation logic. The middleware is registered as a scoped or transient service in the app's service container.

在您的情况下,该注册看起来像这样:

In your case, that registration would look something like this:

public void ConfigureServices(IServiceCollection services)
{
    // ...

    services.AddTransient<RequestCultureMiddleware>();
}

这篇关于使用 IMiddleware 时添加自定义中间件不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆