使用IMiddleware时添加自定义中间件不起作用 - c#

我试图将自定义中间件添加到管道中(为方便起见,我将选择.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”。

我试图找到一个合同...一个基类或一个接口,然后猜测是什么,我们有“ IMiddleware”,它是“ Microsoft.AspNetCore.Http”程序集的一部分。哇,太完美了让我们实现它。

该界面如下所示:

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”,我应该如何准确地注册该中间件?
谢谢。

参考方案

您正在使用factory-based middleware。如这些文档所述,您错过了重要的一步:

...容器中注册的IMiddlewareFactory实例用于解析IMiddleware实现,而不是使用基于约定的中间件激活逻辑。中间件在应用程序的服务容器中注册为scoped or transient service。

在您的情况下,该注册如下所示:

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

    services.AddTransient<RequestCultureMiddleware>();
}

如何在ASP.NET Core Web应用程序中增加JSON反序列化MaxDepth限制 - c#

我们正在将ASP.NET Core 2.1与.NET Framework 4.6.2结合使用。我们有一个客户需要向我们的Web应用程序发送一个很大程度上嵌套的json结构。当他们进行此调用时,我们将输出以下日志并返回错误: 读取器的MaxDepth超过了32。路径“ super.long.path.to property”,第1行,位置42111。”我浏览了…

ASP.NET MVC 5自定义登录,无需脚手架,数据库优先 - c#

我对asp.net和mvc还是很陌生,所以我正在努力学习尽可能多的知识...为此,我从头开始编写博客网站,但是我对身份验证和授权有些困惑。由于我倾向于不真正使用任何脚手架的东西,所以我首先要使用数据库,所以不希望asp.net身份为我创建表。我对散列和加盐密码很酷,并对照数据库检查用户,我遇到的麻烦是将用户设置为登录状态并检查他们应该能够访问什么。我真的很想…

asp.net oledbcommand返回所有行 - c#

我正在使用Oledbconnection连接到Microsoft Access数据库,并且正在使用OleDbCommand检索一些信息。我在数据库中有一个名为retrieveInfo的查询,该查询检索3行数据。字段中有一些重复项,但是应该是这样。我的数据如下所示: Name Email A [email protected] B [email protected] B C@gmai…

asp.net:treeview-显示文本框是否选中? - c#

我需要向用户显示字符串列表。用户可以选择多个字符串。如果选择了一组特定的字符串,则每个字符串旁边都会出现一个文本框。我想做的是向用户显示一个TREEVIEW,每个节点都是字符串之一。他们将通过选中复选框来选择所需的每个字符串。问题:如果用户选择特定的复选框,则我需要一个文本框来显示用户的GET输入。问题:如何从用户使用树形视图获取字符串输入? 参考方案 Tr…

ASP.NET在ContentPlaceHolderID之前添加DIV标签 - c#

我正在尝试使用C# / ASP.NET从Oracle Database中提取日期,如果该日期晚于某天,则隐藏表单的一部分。问题是,通常当我使用div runat=server从ASP.NET内部进行调用时,我只能说CONTROLID.Visible=true即可。出于某种原因,该表格在运行时会在服务器上运行的任何DIV前面加上“ mainContent _”…