c# - 解决 .NET Core 启动中的 Hangfire 依赖项/HttpContext

标签 c# .net autofac hangfire hangfire-autofac

我已经在我的 .NET Core Web 应用程序的 Startup 类中安装并配置了 Hangfire,如下所示(删除了大量非 Hangfire 代码):

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseHangfireServer();
        //app.UseHangfireDashboard();
        //RecurringJob.AddOrUpdate(() => DailyJob(), Cron.Daily);
    }

    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddOptions();
        services.Configure<AppSettings>(Configuration);
        services.AddSingleton<IConfiguration>(Configuration);
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddScoped<IPrincipal>((sp) => sp.GetService<IHttpContextAccessor>().HttpContext.User);
        services.AddScoped<IScheduledTaskService, ScheduledTaskService>();

        services.AddHangfire(x => x.UseSqlServerStorage(connectionString));    
        this.ApplicationContainer = getWebAppContainer(services);
        return new AutofacServiceProvider(this.ApplicationContainer);
    }
}

public interface IScheduledTaskService
{
    void OverduePlasmidOrdersTask();
}

public class ScheduledTaskService : IScheduledTaskService
{
    public void DailyJob()
    {
        var container = getJobContainer();
        using (var scope = container.BeginLifetimeScope())
        {
            IScheduledTaskManager scheduledTaskManager = scope.Resolve<IScheduledTaskManager>();
            scheduledTaskManager.ProcessDailyJob();
        }
    }

    private IContainer getJobContainer()
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule(new BusinessBindingsModule());
        builder.RegisterModule(new DataAccessBindingsModule());
        return builder.Build();
    }
}

如您所见,我正在使用 Autofac 进行 DI。我已设置为每次执行 Hangfire 作业时注入(inject)一个新容器。

目前,我有 UseHangfireDashboard() 以及添加我的重复作业的调用已被注释掉,我在引用 IPrincipal 的行上收到以下错误:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

我知道 Hangfire 没有 HttpContext。我不太确定为什么它甚至会为 Hangfire 线程触发那行代码。我最终需要为我的 IPrincipal 依赖项解析一个服务帐户。

如何解决 Hangfire 和 HttpContext 的问题?

最佳答案

The main problem I'm having now is when I add UseHangfireServer, I then need to resolve HttpContext too

在这里找到Using IoC containers

HttpContext is not available

Request information is not available during the instantiation of a target type. If you register your dependencies in a request scope (InstancePerHttpRequest in Autofac, InRequestScope in Ninject and so on), an exception will be thrown during the job activation process.

So, the entire dependency graph should be available. Either register additional services without using the request scope, or use separate instance of container if your IoC container does not support dependency registrations for multiple scopes.

解决 .net 核心中的作用域依赖项需要一个请求,该请求在启动期间注册和激活作业时不可用。因此,请确保您在启动期间激活所需的服务未使用作用域生命周期注册。

 services.AddTransient<IScheduledTaskManager, ScheduledTaskManageImplementation>();

现在剩下的就是配置应用程序以将该服务与重复作业一起使用,

public class Startup {    
    public IContainer ApplicationContainer { get; private set; }

    public Startup(IHostingEnvironment env) {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public void Configuration(IApplicationBuilder app) {
        // app.AddLogger...

        //add hangfire features
        app.UseHangfireServer();
        app.UseHangfireDashboard();

        //Add the recurring job
        RecurringJob.AddOrUpdate<IScheduledTaskManager>(task => task.ProcessDailyJob(), Cron.Daily);

        //app.UseMvc...
        //...other code
    }

    public IServiceProvider ConfigureServices(IServiceCollection services) {    
        // Adding custom services
        services.AddTransient<IScheduledTaskManager, ScheduledTaskManageImplementation>();
        //add other dependencies...

        // add hangfire services
        services.AddHangfire(x => x.UseSqlServerStorage("<connection string>"));

        //configure Autofac
        this.ApplicationContainer = getWebAppContainer(services);
        //get service provider    
        return new AutofacServiceProvider(this.ApplicationContainer);
    }

    IContainer getWebAppContainer(IServiceCollection service) {
        var builder = new ContainerBuilder();        
        builder.RegisterModule(new BusinessBindingsModule());
        builder.RegisterModule(new DataAccessBindingsModule());
        builder.Populate(services);
        return builder.Build();
    }        


    //...other code
}

引用资料

Hangfire 1.6.0

Integrate HangFire With ASP.NET Core

Using IoC containers

关于c# - 解决 .NET Core 启动中的 Hangfire 依赖项/HttpContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44054578/

相关文章:

C#获取数据包

c# - 无法将 OneTimeEnumerable 转换为 System.Collections.Generic.List

.net - 客户端服务器安装包.NET

c# - 使用 View 注册演示者

autofac - 无法解析参数 'MediatR.ServiceFactory serviceFactory'(带有 Autofac 的 MediatR)

c# - 没有换行符的文本文件中是否有最大行长?

c# - 一个 linq 语句中的 Collection<Collection<Person>> 到 Collection<Person>

c# - 关于反射和权限的快速问题。 .net 2008

c# - WebBrowser 文本选择更改时触发事件

dependency-injection - Sitecore 8.2 Autofac 依赖注入(inject)错误说明