Asp.net core .NET核心中间件-在控制器中访问IApplicationBuilder?

Asp.net core .NET核心中间件-在控制器中访问IApplicationBuilder?,asp.net-core,httpcontext,Asp.net Core,Httpcontext,我需要访问控制器内的IApplicationBuilder 我尝试过的:- 我已经编写了中间件(app.UseMyMiddleware),如下所示 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, I

我需要访问控制器内的IApplicationBuilder

我尝试过的:-

我已经编写了中间件(app.UseMyMiddleware),如下所示

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor httpContextAccessor)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseMyMiddleware();

        app.UseAuthentication();
        app.UseSession();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
public class MyMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task Invoke(HttpContext context)
    {
        ///TODO - Pass IApplicationBuilder to HttpContext 
        await _next(context);
    }
}
public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<MyMiddleware>();
    }
}
public class HangfireSqlServerStorageExtension : Hangfire.JobStorage
{
    private readonly HangfireSqlServerStorage _hangfireSqlServerStorage = new HangfireSqlServerStorage();

    public HangfireSqlServerStorageExtension(string nameOrConnectionString)
    {
        _hangfireSqlServerStorage.SqlServerStorageOptions = new SqlServerStorageOptions();
        _hangfireSqlServerStorage.SqlServerStorage = new SqlServerStorage(nameOrConnectionString, _hangfireSqlServerStorage.SqlServerStorageOptions);
    }
    public HangfireSqlServerStorageExtension(string nameOrConnectionString, SqlServerStorageOptions options)
    {
        _hangfireSqlServerStorage.SqlServerStorageOptions = options;
        _hangfireSqlServerStorage.SqlServerStorage = new SqlServerStorage(nameOrConnectionString, _hangfireSqlServerStorage.SqlServerStorageOptions);
    }

    public void UpdateConnectionString(string nameOrConnectionString)
    {
        _hangfireSqlServerStorage.SqlServerStorage = new SqlServerStorage(nameOrConnectionString, _hangfireSqlServerStorage.SqlServerStorageOptions);
    }

    public override IStorageConnection GetConnection()
    {
        return _hangfireSqlServerStorage.SqlServerStorage.GetConnection();
    }

    public override IMonitoringApi GetMonitoringApi()
    {
        return _hangfireSqlServerStorage.SqlServerStorage.GetMonitoringApi();
    }
}
public class Startup
{
    ///Other necessary code here
    
    public static HangfireSqlServerStorageExtension HangfireSqlServerStorageExtension { get; private set; }

    public void ConfigureServices(IServiceCollection services)
    {
       ///Other necessary code here
       
        HangfireSqlServerStorageExtension = new HangfireSqlServerStorageExtension("DBConnecttionString"));
        services.AddSingleton<HangfireSqlServerStorageExtension>(HangfireSqlServerStorageExtension);
        services.AddHangfire(configuration => configuration.SetDataCompatibilityLevel(CompatibilityLevel.Version_170));
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor httpContextAccessor)
    {
       //Other necessary code here

        app.UseHangfireDashboard("/Dashboard", new DashboardOptions(), HangfireSqlServerStorageExtension);

        //Other necessary code here
    }
}
//此方法由运行时调用。使用此方法配置HTTP请求管道。
公共无效配置(IApplicationBuilder应用程序、IHostingEnvironment环境、IHttpContextAccessor httpContextAccessor)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
其他的
{
app.UseExceptionHandler(“/Home/Error”);
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMyMiddleware();
app.UseAuthentication();
app.UseSession();
app.UseMvc(路由=>
{
routes.MapRoute(
名称:“默认”,
模板:“{controller=Home}/{action=Index}/{id?}”);
});
}
公共类中间件
{
private readonly RequestDelegate\u next;
公共MyMiddleware(RequestDelegate下一步)
{
_下一个=下一个;
}
公共异步任务调用(HttpContext上下文)
{
///TODO-将IApplicationBuilder传递给HttpContext
等待下一步(上下文);
}
}
公共静态类MiddlewareExtensions
{
公共静态IAApplicationBuilder UseMyMiddleware(此IAApplicationBuilder)
{
返回builder.UseMiddleware();
}
}
但我不知道如何在Invoke方法中将IAApplicationBuilder传递给HttpContext。所以,我可以在控制器中使用它。 我还提到了以下问题的答案

  • 问题:-

  • 如何将IAApplicationBuilder传递给Invoke方法中的HttpContext,以便在控制器中使用它

  • 除了中间件之外,还有什么更好的方法可以访问控制器内部的IApplicationBuilder吗


  • 在完成应用程序构建阶段后(运行
    Configure
    方法后),您不能访问
    iaapplicationbuilder
    的任何位置。根本无法注射。 但是,为了在运行时根据请求数据(从
    HttpContext
    )插入或配置中间件,您可以使用
    .UseWhen
    。另一个终端中间件是
    .MapWhen
    ,但我认为这不适合您的情况。以下是
    .UseWhen
    的示例:

    public static class MiddlewareExtensions
    {
        public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder builder)
        {
            var allOptions = new [] {"option 1","option 2"};
            foreach(var option in allOptions){
                var currentOption = option;
                builder.UseWhen(context => {
                  //suppose you can get the user's selected option from query string
                  var selectedOption = context.Request.Query["option_key"];
                  return selectedOption == currentOption;
                }, app => {
                   //your MyMiddleware is supposed to accept one argument
                   app.UseMiddleware<MyMiddleware>(currentOption);
                });
            }
            return builder;
        }
    }
    

    您必须决定如何从用户处获取所选选项(在上面的示例中,我是从
    查询字符串
    获取的)。您也可以从
    Cookie
    获取它(以记住用户的选择),或者从其他来源获取它,例如路由数据、头、表单、请求正文。我认为这是另一个问题,因此,如果您对此有问题,请提出另一个问题。

    IApplicationBuilder的设计不是为了按您希望的方式工作。相反,如果您在构建时创建了一些数据,并且希望这些数据可用于中间件,请向服务中添加一个单例,并将该单例注入中间件。

    首先感谢@Kingking和@GlennSills提供的解决方案和有价值的评论

    我已经解决了这个问题

    创建了一个继承自Hangfire.JobStorage的类,如下所示

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor httpContextAccessor)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }
    
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseMyMiddleware();
    
            app.UseAuthentication();
            app.UseSession();
    
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    public class MyMiddleware
    {
        private readonly RequestDelegate _next;
    
        public MyMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task Invoke(HttpContext context)
        {
            ///TODO - Pass IApplicationBuilder to HttpContext 
            await _next(context);
        }
    }
    public static class MiddlewareExtensions
    {
        public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<MyMiddleware>();
        }
    }
    
    public class HangfireSqlServerStorageExtension : Hangfire.JobStorage
    {
        private readonly HangfireSqlServerStorage _hangfireSqlServerStorage = new HangfireSqlServerStorage();
    
        public HangfireSqlServerStorageExtension(string nameOrConnectionString)
        {
            _hangfireSqlServerStorage.SqlServerStorageOptions = new SqlServerStorageOptions();
            _hangfireSqlServerStorage.SqlServerStorage = new SqlServerStorage(nameOrConnectionString, _hangfireSqlServerStorage.SqlServerStorageOptions);
        }
        public HangfireSqlServerStorageExtension(string nameOrConnectionString, SqlServerStorageOptions options)
        {
            _hangfireSqlServerStorage.SqlServerStorageOptions = options;
            _hangfireSqlServerStorage.SqlServerStorage = new SqlServerStorage(nameOrConnectionString, _hangfireSqlServerStorage.SqlServerStorageOptions);
        }
    
        public void UpdateConnectionString(string nameOrConnectionString)
        {
            _hangfireSqlServerStorage.SqlServerStorage = new SqlServerStorage(nameOrConnectionString, _hangfireSqlServerStorage.SqlServerStorageOptions);
        }
    
        public override IStorageConnection GetConnection()
        {
            return _hangfireSqlServerStorage.SqlServerStorage.GetConnection();
        }
    
        public override IMonitoringApi GetMonitoringApi()
        {
            return _hangfireSqlServerStorage.SqlServerStorage.GetMonitoringApi();
        }
    }
    
    public class Startup
    {
        ///Other necessary code here
        
        public static HangfireSqlServerStorageExtension HangfireSqlServerStorageExtension { get; private set; }
    
        public void ConfigureServices(IServiceCollection services)
        {
           ///Other necessary code here
           
            HangfireSqlServerStorageExtension = new HangfireSqlServerStorageExtension("DBConnecttionString"));
            services.AddSingleton<HangfireSqlServerStorageExtension>(HangfireSqlServerStorageExtension);
            services.AddHangfire(configuration => configuration.SetDataCompatibilityLevel(CompatibilityLevel.Version_170));
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor httpContextAccessor)
        {
           //Other necessary code here
    
            app.UseHangfireDashboard("/Dashboard", new DashboardOptions(), HangfireSqlServerStorageExtension);
    
            //Other necessary code here
        }
    }
    
    HangfireSqlServerStorage.cs

    在上面的HangfireSqlServerStorageExtension类中使用

    public class HangfireSqlServerStorage
    {
        public SqlServerStorage SqlServerStorage { get; set; }
        public SqlServerStorageOptions SqlServerStorageOptions { get; set; }
    }
    
    Startup.cs

    在启动文件中,为HangfireSqlServerStorageExtension实例添加singleton服务,并按如下方式配置hangfire仪表板

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor httpContextAccessor)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }
    
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseMyMiddleware();
    
            app.UseAuthentication();
            app.UseSession();
    
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    public class MyMiddleware
    {
        private readonly RequestDelegate _next;
    
        public MyMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task Invoke(HttpContext context)
        {
            ///TODO - Pass IApplicationBuilder to HttpContext 
            await _next(context);
        }
    }
    public static class MiddlewareExtensions
    {
        public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<MyMiddleware>();
        }
    }
    
    public class HangfireSqlServerStorageExtension : Hangfire.JobStorage
    {
        private readonly HangfireSqlServerStorage _hangfireSqlServerStorage = new HangfireSqlServerStorage();
    
        public HangfireSqlServerStorageExtension(string nameOrConnectionString)
        {
            _hangfireSqlServerStorage.SqlServerStorageOptions = new SqlServerStorageOptions();
            _hangfireSqlServerStorage.SqlServerStorage = new SqlServerStorage(nameOrConnectionString, _hangfireSqlServerStorage.SqlServerStorageOptions);
        }
        public HangfireSqlServerStorageExtension(string nameOrConnectionString, SqlServerStorageOptions options)
        {
            _hangfireSqlServerStorage.SqlServerStorageOptions = options;
            _hangfireSqlServerStorage.SqlServerStorage = new SqlServerStorage(nameOrConnectionString, _hangfireSqlServerStorage.SqlServerStorageOptions);
        }
    
        public void UpdateConnectionString(string nameOrConnectionString)
        {
            _hangfireSqlServerStorage.SqlServerStorage = new SqlServerStorage(nameOrConnectionString, _hangfireSqlServerStorage.SqlServerStorageOptions);
        }
    
        public override IStorageConnection GetConnection()
        {
            return _hangfireSqlServerStorage.SqlServerStorage.GetConnection();
        }
    
        public override IMonitoringApi GetMonitoringApi()
        {
            return _hangfireSqlServerStorage.SqlServerStorage.GetMonitoringApi();
        }
    }
    
    public class Startup
    {
        ///Other necessary code here
        
        public static HangfireSqlServerStorageExtension HangfireSqlServerStorageExtension { get; private set; }
    
        public void ConfigureServices(IServiceCollection services)
        {
           ///Other necessary code here
           
            HangfireSqlServerStorageExtension = new HangfireSqlServerStorageExtension("DBConnecttionString"));
            services.AddSingleton<HangfireSqlServerStorageExtension>(HangfireSqlServerStorageExtension);
            services.AddHangfire(configuration => configuration.SetDataCompatibilityLevel(CompatibilityLevel.Version_170));
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor httpContextAccessor)
        {
           //Other necessary code here
    
            app.UseHangfireDashboard("/Dashboard", new DashboardOptions(), HangfireSqlServerStorageExtension);
    
            //Other necessary code here
        }
    }
    

    iaapplicationbuilder
    设计用于在启动时构建应用程序,运行一次,而不是在以后运行时运行。因此,我认为它不能为您提供任何运行时服务或API,您想要它做什么?这比如何使其可用更重要。@KingKing我想使用此IApplicationBuilder在控制器中配置Hangfire。您可以参考问题了解更多详细信息您以后无法访问
    iaapplicationbuilder
    ,但您可以在运行时使用
    useawhen
    插入中间件。但是,筛选条件不能利用您的
    MVC模型绑定
    ,因为您只有
    HttpContext
    作为输入,您自己从原始源(查询字符串、路由数据、标题、表单、请求正文)提取请求数据。你可以通过某种方式实现一个设置,记住或发送每个请求的所选选项)。@KingKing你能给我一个例子吗?我该怎么做?@KingKing谢谢!对于您的努力,我会检查并让您知道。谢谢您提供的信息。有没有其他办法来解决这个问题?我尝试了以下答案中提供的KingKing方法,但使用该方法,我无法根据“builder.UseWhen”条件更改“app.UseHangfireDashboard”的配置。(它仅在应用程序启动时配置)。查看一个关于如何在控制器中使用IApplicationBuilder的示例将非常有用。如果您告诉我,我可能可以为您提供一个解决方案。@开发者我很确定您不知道如何应用我的解决方案,
    。使用when
    是您可以尝试的唯一选项。但看起来你不需要解决它,好吧。许多用户通过来回响应来获得最终解决方案,但您只是保持沉默,这样就没有机会让其他人提供帮助。“那只是你的选择。”金金对迟迟不答复深表歉意。我已经使用了您的解决方案,但使用该解决方案,我无法根据条件(使用.UseWhen)更改hangfire配置(表示hangfire连接字符串)。现在,我补充了我的答案。感谢您的努力,很抱歉延迟回复。