I'm using structuremap with hangfire on asp.net core, no error on application but hangfire not process queue/schedule task even though data already on database. Here my snippet configuration
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// setup automapper
var config = new AutoMapper.MapperConfiguration(cfg =>
{
cfg.AddProfile(new AutoMapperProfileConfiguration());
});
var mapper = config.CreateMapper();
services.AddSingleton(mapper);
// Bind settings parameter
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.Configure<RouteOptions>(options => options.LowercaseUrls = true);
services.AddDbContext<DefaultContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddHangfire(options =>
options.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
// ASP.NET use the StructureMap container to resolve its services.
return ConfigureIoC(services);
}
public IServiceProvider ConfigureIoC(IServiceCollection services)
{
var container = new Container();
GlobalConfiguration.Configuration.UseStructureMapActivator(container);
container.Configure(config =>
{
// Register stuff in container, using the StructureMap APIs...
config.Scan(_ =>
{
_.AssemblyContainingType(typeof(Startup));
_.WithDefaultConventions();
_.AddAllTypesOf<IApplicationService>();
_.ConnectImplementationsToTypesClosing(typeof(IOptions<>));
});
config.For<JobStorage>().Use(new SqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
config.For<IJobFilterProvider>().Use(JobFilterProviders.Providers);
config.For<ILog>().Use(c => LoggerFactory.LoggerFor(c.ParentType)).AlwaysUnique();
XmlDocument log4netConfig = new XmlDocument();
log4netConfig.Load(File.OpenRead("log4net.config"));
var repo = LogManager.CreateRepository(
Assembly.GetEntryAssembly(), typeof(log4net.Repository.Hierarchy.Hierarchy));
XmlConfigurator.Configure(repo, log4netConfig["log4net"]);
//Populate the container using the service collection
config.Populate(services);
});
return container.GetInstance<IServiceProvider>();
}
Is there any better way using hangfire and structuremap on asp.net core? Am I missing something so hangfire not working properly?
My Hangfire structure map implementation
using Hangfire;
using StructureMap;
namespace Lumochift.Helpers
{
/// <summary>
/// Bootstrapper Configuration Extensions for StructureMap.
/// </summary>
public static class StructureMapBootstrapperConfigurationExtensions
{
/// <summary>
/// Tells bootstrapper to use the specified StructureMap container as a global job activator.
/// </summary>
/// <param name="configuration">Bootstrapper Configuration</param>
/// <param name="container">StructureMap container that will be used to activate jobs</param>
public static void UseStructureMapActivator(this GlobalConfiguration configuration, IContainer container)
{
configuration.UseActivator(new StructureMapJobActivator(container));
}
}
}
using Hangfire;
using StructureMap;
using System;
namespace Lumochift.Helpers
{
public class StructureMapJobActivator : JobActivator
{
private readonly IContainer _container;
/// <summary>
/// Initializes a new instance of the <see cref="StructureMapJobActivator"/>
/// class with a given StructureMap container
/// </summary>
/// <param name="container">Container that will be used to create instances of classes during
/// the job activation process</param>
public StructureMapJobActivator(IContainer container)
{
if (container == null) throw new ArgumentNullException(nameof(container));
_container = container;
}
/// <inheritdoc />
public override object ActivateJob(Type jobType)
{
return _container.GetInstance(jobType)
}
/// <inheritdoc />
public override JobActivatorScope BeginScope(JobActivatorContext context)
{
return new StructureMapDependencyScope(_container.GetNestedContainer());
}
private class StructureMapDependencyScope : JobActivatorScope
{
private readonly IContainer _container;
public StructureMapDependencyScope(IContainer container)
{
_container = container;
}
public override object Resolve(Type type)
{
return _container.GetInstance(type);
}
public override void DisposeScope()
{
_container.Dispose();
}
}
}
}
Example hangfire call on controller
BackgroundJob.Enqueue<CobaService>((cb) => cb.GetCoba());
BackgroundJob.Schedule<CobaService>((cb) => cb.GetCoba(), TimeSpan.FromSeconds(5) );
Screenshot:
You should use Hangfire.AspNetCore nuget package.
It uses AspNetCoreJobActivator
as the default job activator, so you don't have to create your own.
AspNetCoreJobActivator
uses IServiceScope.ServiceProvider.GetRequiredService(type)
method to resolve dependencies. The same ServiceProvider, that you return from ConfigureServices
, with all the services configured by structuremap.
Implementation of AddHangfire
method
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With