I use Hangfire package to fire background job.
However, It's not able to resolve services from the OrchardCore. In this case, It's IUserService
Actual: My Hangfire's jobs can't resolve IUserService
Expect: My Hangfire's jobs should be able to resolve IUserService
Importance notes:
IUserService, Checkout my source code to preproduce the issue here: https://github.com/hung-doan/OCHangFireIssue
NOTE: Before running the code, you should
Step 1: Fire a job via https://localhost:44342/api/test/new-job
Step 2: Access the dashboard at https://localhost:44342/hangfire
Step 3: Got execution error from the hangfire history
Exception:

System.InvalidOperationException
Unable to resolve service for type 'OrchardCore.Users.Services.IUserService' while attempting to activate 'OCHangFire.Jobs.MyBackgroundJob'.
System.InvalidOperationException: Unable to resolve service for type 'OrchardCore.Users.Services.IUserService' while attempting to activate 'OCHangFire.Jobs.MyBackgroundJob'.
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type)
at Hangfire.AspNetCore.AspNetCoreJobActivatorScope.Resolve(Type type)
at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass9_0.<PerformJobWithFilters>b__0()
at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass9_1.<PerformJobWithFilters>b__2()
at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable`1 filters)
at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)
Any idea/direction to resolve the problem are appreciated. Thanks everyone.
I鈥檓 not an expert on this but I did get it to work. One thing that helped was to put all of the Hangfire and my custom services in the same Orchard Core module.
Yes through a module startup so that there are not registered at the app level, but when we compose a tenant container
Without using a module you can do the same from the app but by using our OrchardCoreBuilder helpers
services.AddOrchardCms()
.ConfigureServices(tenantServices =>
{
...
})
.Configure((tenantAppBuilder, ...) =>
{
...
})
;
Also don't use app.UseRouting(); in you main app startup, it is done when we built a tenant pipeline (per tenant)
thanks @mattobox , @jtkech.
I implemented your suggestion here (without module): https://github.com/hung-doan/OCHangFireIssue/compare/bugfix/7437-workaround?expand=1
It seems to work on my basic test. But let me check in more complex scenarios and get back later.
Btw, I think it's just a workaround. From my point of view, OrchardCore should not override the standard behavior of service containers from the .NET Core Framework.
Yes i understand ;)
But OrchardCore is multi tenants (multi sites), we have at least the Default tenant, and each tenant (composed of modules / features) run in an isolated container with their own services, startup filters, configured pipeline and so on.
We have app level services that we pass to tenant containers, but to make things working, e.g. app level routing sevices are not passed. You can still use app level routing but no tenant is aware of it, and the related code is not executed in a tenant context, e.g. we use at the app level app.UseStaticFiles() even we also have tenant level static file providers.
Most helpful comment
Yes through a module startup so that there are not registered at the app level, but when we compose a tenant container
Without using a module you can do the same from the app but by using our OrchardCoreBuilder helpers
Also don't use
app.UseRouting();in you main app startup, it is done when we built a tenant pipeline (per tenant)