# Loss of configurability with AspNetCore implementation

**URL:** <https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942>\
**Category:** question\
**Tags:** ioc-container, job-filters, aspnetcore\
**Created:** [February 11, 2017, 1:08am UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942 "2017-02-11T01:08:25Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![nickalbrecht](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/nickalbrecht/32/869_2.png) [@nickalbrecht](https://discuss.hangfire.io/u/nickalbrecht)\
**Post date:** [February 11, 2017, 1:08am UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/1 "2017-02-11T01:08:25Z")

</div>

I’m trying to execute logic that will entail manipulating database records using Hangfire. I manage the transaction for this explicitly using a very basic implementation of a IUnitOfWork class that I have registered with the default resolver for ASPNET Core (I’m using MVC Core). However the `JobActivatorScope` that is created internally to the `CoreBackgroundJobPerformer` is created and subsequently disposed before I can do anything with it, regardless if the job was successful or failed.

After some digging I found that the `JobActivatorScope.Current` will have an instance to this scope, but control of the execution before this scope is disposed, because of the `using` statement, never gets handed outside of `CoreBackgroundJobPerformer.Perform(PerformContext context)`. Is there any way to try and execute code (to commit or rollback my transaction) before the `JobActivatorScope` is disposed?

I’m currently using this exact pattern in an MVC 5 site, but I had implemented it by storing my own IoC scope inside of a ThreadStatic variable in a custom `JobActivator` and a custom `JobFilter`. Now that the scope is being implicitly created and used by Hangfire, I have much less control over how it’s used.

---

<div class="post-metadata">

**Author:** ![pieceofsummer](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/pieceofsummer/32/785_2.png) [@pieceofsummer](https://discuss.hangfire.io/u/pieceofsummer)\
**Post date:** [February 11, 2017, 1:47am UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/2 "2017-02-11T01:47:22Z")

</div>

I think the easiest way is to make your own `JobActivator` / `JobActivatorScope` subclasses (based on `AspNetCoreJobActivator` / `Scope` source code), and implement your logic inside `JobActivatorScope.DisposeScope()` before actually disposing the underlying `IServiceScope`.

Being inside `JobActivatorScope`, you theoretically have the `JobActivatorContext` (by passing it from `JobActivator.BeginScope()` to your newly created `JobActivatorScope` instance), so you may know the identifier of the job (`JobActivatorContext.BackgroundJob.Id`) and its parameters (`JobActivatorContext.GetJobParameter` / `SetJobParameter`), and also have access to the entire `IStorageConnection`.

On the other hand, it would be nearly impossible to access `ProcessContext` from there, so if you’re using `PerformContext.Items` to pass data between job filters, you’re out of luck.

---

<div class="post-metadata">

**Author:** ![nickalbrecht](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/nickalbrecht/32/869_2.png) [@nickalbrecht](https://discuss.hangfire.io/u/nickalbrecht)\
**Post date:** [February 13, 2017, 11:38pm UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/3 "2017-02-13T23:38:15Z")

</div>

The problem is that I need to have transaction handling logic for when the scope is no longer needed. That is to say, I don’t really care about when/how the scope is created ( can deal with that in the services setup of the ASPNET Core site), I need to conditionally test if any exceptions were called within hangfire and either call Commit or Rollback on the transaction. When I first did this (not in ASPNET Core), I could test for exceptions on a `JobFilterAttribute.OnPerformed()`, since it’s PerformedContext had the information I needed, and I had managed the scope myself, and had access to it on the JobActivator. But OnPerformed() this is not called until after the scope has been disposed of already, so it’s too late. Also, calling a commit DB changes from inside of a dispose method is a BAD practice, Ideally I don’t want dispose calling rollback either, but that’s one I’ve had to concede to out of necessity. Dispose should be doing nothing other than closing/releasing resources. It should be Idempotent. `DisposeScope` is not called by Hangfire directly from the looking at the code anyway, it’s actually called from inside of the Dispose() method. So It’s not something I can expect to have any context of the job that just ran (successful or otherwise).

I took another look, and the only way I can see being able to do what I need is to either try to ignore the ASPNET Core implementation and use my old logic of custom the `JobFilter`/`JobActivator` for managing my IoC scope (this feels very hacky, and I haven’t figured out how to add `JobFilterAttribute`s using the new ASPNET Core implementation), or to try and reimplement the `IBackgroundJobPerformer` using the current code as a base and inject the necessary logic/events I need into my custom version of it (less hacky, but this seems overkill/shotgun approach), I was really hoping there was some sort of event/method called in a `finally` block of the `JobPerformer` to give the developer a chance to do some scope cleanup task(s) in the `JobActivator`, but it doesn’t appear to be the case. I guess I’m more trying to determine if this is an actual limitation/intentional behavior, and if my exposing a way for me to do this will cause problems. But I don’t think I have a choice in order to get the behavior I need.

---

<div class="post-metadata">

**Author:** ![nickalbrecht](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/nickalbrecht/32/869_2.png) [@nickalbrecht](https://discuss.hangfire.io/u/nickalbrecht)\
**Post date:** [February 14, 2017, 12:28am UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/4 "2017-02-14T00:28:13Z")

</div>

Crap, and I can’t even implement my own BackgroundJobPerformer, too many of the classes used are marked as internal. I’d end up duplicating a LOT of classes just for the sake of being able to essentially add a call to let me do `uow.Commit()`, which is ridiculous.  
I don’t know of anyway to get this to work using the ASPNET Core implementation for Hangfire. I may have to set it up all manually and keep the logic from a different project to override the behavior of the IoC service resolver to be done in my custom JobFilter/Activator. Which is going to be ugly given that I believe it depended upon Owin, which ASPNET Core, doesn’t use. It’s either that or drop Hangfire in favor of one that allows me to control the scope of the service providers. :-/

---

<div class="post-metadata">

**Author:** ![nickalbrecht](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/nickalbrecht/32/869_2.png) [@nickalbrecht](https://discuss.hangfire.io/u/nickalbrecht)\
**Post date:** [February 15, 2017, 11:45pm UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/5 "2017-02-15T23:45:28Z")

</div>

> Changing my question title now that I’ve had larger problems with configuration

So I thought I had a solution to this, but when trying to implement it I realized that the ASPNET Core implementation for Hangfire is hardcoded. As soon as you call `services.AddHangfire()` inside of of your `Startup.ConfigureServices()`, you’re forced to use `AspNetCoreJobActivator`, It will ignore anything else you have setup to override which Activator to use.

Ex.

```
public void ConfigureServices(IServiceCollection services)
{
    //.... Other setup for services
    services.AddHangfire(x =>
    {
        x.UseActivator(new MyCustomJobActivator());
    });
    //.... Other setup for services
}

//OR

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    //...other middleware setup
    app.UseHangfireServer(new BackgroundJobServerOptions()
    {
        Activator = new MyCustomJobActivator()
    });
    //...other middleware setup
}

```

The above still seems to result in Hangfire using the `AspNetCoreJobActivator` type, instead of the one specified using either method.

I even tried calling the older method `GlobalConfiguration.Configuration.UseActivator(new MyCustomJobActivator())` with no success. So at the moment, short of cloning the code from the `Hangfire.AspNetCore` namespace, I can find zero way to customize the way the AspNetCore implementation works.

It’s also worth noting that while previous version of Hangfire used the `ActivateJob` method on the `JobActivator` class, the AspNetCore implementation just uses the Job activator as a `JobActivatorScope` factory, and nothing more (uses the `Resolve()` method on the `JobActivatorScope` instead).

All in all, a lot of breaking changes to the way Hangfire runs tasks.

---

<div class="post-metadata">

**Author:** ![pieceofsummer](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/pieceofsummer/32/785_2.png) [@pieceofsummer](https://discuss.hangfire.io/u/pieceofsummer)\
**Post date:** [February 16, 2017, 12:01am UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/6 "2017-02-16T00:01:02Z")

</div>

You might be interested in [https://github.com/HangfireIO/Hangfire/pull/800](https://github.com/HangfireIO/Hangfire/pull/800). It allows to replace almost all internal components with the custom ones from IoC container.

---

<div class="post-metadata">

**Author:** ![nickalbrecht](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/nickalbrecht/32/869_2.png) [@nickalbrecht](https://discuss.hangfire.io/u/nickalbrecht)\
**Post date:** [February 16, 2017, 9:20pm UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/7 "2017-02-16T21:20:14Z")

</div>

That’s a great direction to go, but I would point out that in the current implementation in the `Hangfire.AspNetCore/HangfireServiceCollectionExtensions.cs` file, the default behavior for setting up the resolution of `IGlobalConfiguration` in the `AddHangfire()` extension method is hardcoded, and will ignore whatever activator or logger you specify anywhere else in your configuration.

---

<div class="post-metadata">

**Author:** ![pieceofsummer](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/pieceofsummer/32/785_2.png) [@pieceofsummer](https://discuss.hangfire.io/u/pieceofsummer)\
**Post date:** [February 17, 2017, 12:07am UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/8 "2017-02-17T00:07:12Z")

</div>

Added some comments there.

The current implementation might ignore the activator/logger indeed, but the proposed implementation will always resolve the activator from the IoC container, so the default values stored in `JobActivator.Current` during `AddHangfire()` method call won’t break anything.

---

<div class="post-metadata">

**Author:** ![kYann](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/kyann/32/1305_2.png) [@kYann](https://discuss.hangfire.io/u/kYann)\
**Post date:** [April 24, 2018, 10:53am UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/9 "2018-04-24T10:53:51Z")

</div>

Hello @nickalbrecht,

I do have the same issue as you, can you tell me how you ended up doing it ?  
And also could you open source it ?

Thanks,

Yann

---

<div class="post-metadata">

**Author:** ![kYann](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/kyann/32/1305_2.png) [@kYann](https://discuss.hangfire.io/u/kYann)\
**Post date:** [April 24, 2018, 3:23pm UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/10 "2018-04-24T15:23:46Z")

</div>

I ended up doing a Filter that create the ISessionScope OnPerforming. I store this session scope in a ThreadStatic. I take this session scope in the ActivatorJob and use it in a ActivatorJobScope. I dispose this scope in the filter. And also do the commit in the filter.

---

<div class="post-metadata">

**Author:** ![jruiz](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/jruiz/32/1434_2.png) [@jruiz](https://discuss.hangfire.io/u/jruiz)\
**Post date:** [November 6, 2018, 3:42pm UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/11 "2018-11-06T15:42:45Z")

</div>

Hi @kYann,

could you share your solution?

Kind regards,  
Jordi

---

<div class="post-metadata">

**Author:** ![nickalbrecht](https://dub1.discourse-cdn.com/flex017/user_avatar/discuss.hangfire.io/nickalbrecht/32/869_2.png) [@nickalbrecht](https://discuss.hangfire.io/u/nickalbrecht)\
**Post date:** [December 1, 2020, 10:11pm UTC](https://discuss.hangfire.io/t/loss-of-configurability-with-aspnetcore-implementation/2942/12 "2020-12-01T22:11:58Z")

</div>

I keep running into issues with this so I’m having to revisit it again and see if I can come up with a solution that will allow me to implement a Unit of Work (UoW) pattern that will both work with Hangfire, and also correctly handle asynchronous methods and awaits. It needs to correctly handle ending of the UoW so that it either uses something like `ConfigureAwait(true)` to force it to finish on the same thread, or correctly handle the ending of the UoW when it ends on a different thread, storing the transaction somewhere that async/await pattern will work with, or try and obtain the current transaction from the ServiceProviderScope.
