I needed a way to run background jobs and found out about HangFire. I succesfully installed everything but I can't seem to get it working together with Windsor.
The problem:
When I use any of my dependencies in my background job function I get the following error in my HangFire dashboard :
System.InvalidOperationException: HttpContext.Current is null.
PerWebRequestLifestyle can only be used in ASP.Net
I searched around and found out that I should use the NuGet package Castle.Windsor.Lifestyles for Hybrid lifestyles. But this does not work for me.
This is my code:
Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Set up IoC Container
var container = new WindsorContainer(Server.MapPath("~/Configuration/IoC/windsor.config"));
// Set up HangFire with IoC
JobActivator.Current = new WindsorJobActivator(container.Kernel);
}
Startup.cs:
public void Configuration(IAppBuilder app)
{
GlobalConfiguration.Configuration.UseSqlServerStorage("ILVO");
app.UseHangfireServer();
app.UseHangfireDashboard();
}
ServiceInstaller.cs:
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register
(
Component.For<ApplicationContextBuilder>().ImplementedBy<ApplicationContextBuilder>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<IApplicationContextProvider>().ImplementedBy<ApplicationContextProvider>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<ICacheService>().ImplementedBy<CacheService>().LifestyleSingleton(),
Component.For<ISessionProvider>().ImplementedBy<SessionProvider>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<IRepository>().ImplementedBy<Repository>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<IEmployeeService>().ImplementedBy<EmployeeService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<IGeneralService>().ImplementedBy<GeneralService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<ITaskService>().ImplementedBy<TaskService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<ISuggestionService>().ImplementedBy<SuggestionService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<IAnnouncementService>().ImplementedBy<AnnouncementService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<IUploadService>().ImplementedBy<UploadService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<ITaskTrackingService>().ImplementedBy<TaskTrackingService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<IRequestVpnService>().ImplementedBy<RequestVpnService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<IEmailService>().ImplementedBy<EmailService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<IEmployeePlannerService>().ImplementedBy<EmployeePlannerService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<ISalaryToolService>().ImplementedBy<SalaryToolService>().LifeStyle.HybridPerWebRequestTransient(),
Component.For<IAccessRightService>().ImplementedBy<AccessRightService>().LifeStyle.HybridPerWebRequestTransient()
);
}
Is there any solution for this? I would really like to run database operations in my background job.
Appreciate any help! Thx.
SOLUTION
I made a separate IoC container for HangFire only with the services I need! I also made a class BackroundJobHelper which I store all my functions I need to run in HangFire.
Global.asax
private WindsorContainer _hangFireContainer;
// Set up IoC Container for HangFire
_hangFireContainer = new WindsorContainer();
_hangFireContainer.Register(
Component.For<BackgroundJobHelper>(),
Component.For<ICacheService>().ImplementedBy<CacheService>().LifestylePerThread(),
Component.For<ISessionProvider>().ImplementedBy<SessionProvider>().LifestylePerThread(),
Component.For<IRepository>().ImplementedBy<Repository>().LifestylePerThread(),
Component.For<IEmployeePlannerService>().ImplementedBy<EmployeePlannerService>().LifestylePerThread(),
Component.For<ISalaryToolService>().ImplementedBy<SalaryToolService>().LifestylePerThread()
);
JobActivator.Current = new WindsorJobActivator(_hangFireContainer.Kernel);
BackgroundJobHelper.cs
public class BackgroundJobHelper
{
private readonly IEmployeePlannerService _employeePlannerService;
private readonly ISalaryToolService _salaryToolService;
public BackgroundJobHelper()
{
}
public BackgroundJobHelper(IEmployeePlannerService employeePlannerService, ISalaryToolService salaryToolService)
{
_employeePlannerService = employeePlannerService;
_salaryToolService = salaryToolService;
}
}
Controller
In the controller I call my BackgroundJobHelper class with the function I want to run in HangFire.
BackgroundJob.Enqueue(() => _backgroundJobHelper.Function());
The problem is that Hangfire runs it's own server (thread) independent of the housing app.
Your container is running inside what looks like an MVC application. So at registration time, the HttpContext is available and your services are getting registered with the PerRequest scope.
When you get to running in Hangfire, HttpContext is unavailable. Register any services you want to use in Hangfire with the PerThread scope. If you are sharing these components between the web application and your background threads, this may make things a little wonky. See here
You might want to segregate the components that are going to run in the background and register then PerThread as opposed to sharing PerThread components with both the Hangfire process and your web process.
It tells you here that you can't use PerRequest with Hangfire because of the issue you are seing.
I managed to do it using
https://github.com/BredStik/HangFire.Windsor
and
http://docs.hangfire.io/en/latest/background-methods/using-ioc-containers.html
Basically, you register your Jobs/Services and volia.
Registering is done via you DI provider (Windsor) the usual way.
protected void Application_Start()
{
_container = new WindsorContainer();
/* Register types */
/* _container.Register(Component.For<ISomeInterface>().ImplementedBy<SomeImplementation>()); */
JobActivator.Current = new WindsorJobActivator(_container.Kernel);
}
I basically reused existing stuff and just added Jobs on Container.
windsorContainer.Register(Component.For<SomeJob>().ImplementedBy<SomeJob>());
With windsorContainer being IWindsorContainer. This is done in Global.asax.
In your Startup, you call:
RecurringJob.AddOrUpdate<SomeJob>(x => x.Run(null), Properties.Settings.Default.SomeJobCron);
Related
I am struggling to determine if this is the correct method for injecting dependencies from my Console Application Main method into my primary application class instance.
I have the following code:
Program Class
static void Main(string[] args)
{
var container = new SimpleInjector.Container();
// Registrations here.
container.Register<ILogger, FileLogger>();
//Verify the container.
container.Verify();
ILogger log = container.GetInstance<ILogger>();
log.Info("Logging From Main Method");
//Start Main Agent
MainAgent agent = new MainAgent(log);
agent.Start();
}
Main Agent Class
public class MainAgent
{
private ILogger log;
public MainAgent(ILogger _log)
{
log = _log;
}
public void Start()
{
//Main Application Code here.
Console.WriteLine("main Agent Started.");
log.Info("Logging through logger in MainAgent Class");
Console.ReadLine();
}
}
I come from a background of writing DotNetCore applications in ASP.Net Core, so I am used to how the DI works with that, registering a service into the pipeline, and them all being available for me to cherry pick in each controller's Constructor.
My worry is I may have 20-30 services, all of which will all need to be injected in as parameters each time I “New Up” a new instance of a class for them to be avaliable to the constructor in my new class.
Am I missing some magical feature which will just make all my registered services available in any newly initialized constructor for me to reference as I do with ASP.Net Core?
No, there is no magic.
What you are missing is that AspNetCore automatically resolves your controller under the covers, which resolves the entire object graph of dependencies that controller has (that is, any dependencies of the controller, dependencies of those dependencies, etc.)
Similarly, in a console app, you need to resolve the entire object graph (usually at startup).
static void Main(string[] args)
{
// Begin Composition Root
var container = new SimpleInjector.Container();
// Registrations here.
container.Register<ILogger, FileLogger>();
container.Register<IMainAgent, MainAgent>();
//Verify the container.
container.Verify();
// End Composition Root
MainAgent agent = container.GetInstance<IMainAgent>();
//Start Main Agent
agent.Start();
}
Effectively the "agent" is should be considered to be the entire application. The console is just a shell to set everything in motion. Do note that it would probably be sensible in most situations to pass in the args from the console app, so they can be parsed and responded to by the "agent" as appropriate.
agent.Start(args);
Am I missing some magical feature which will just make all my registered services available in any
Simple answer yes you are SimpleInjector supports direct object creation
var agent = container.GetInstance<MainAgent>();
With out the need to register the instance at all.
You can make an interface and then register like you do ILogger but making the method virtual and using directly the class name is also fine. You can read more on the subject here
I have an C# MVC application. I am using Unity Container to resolve my dependencies. For injecting dependencies inside MVC controller, I am using constructor injection. To achieve this I have replaced the MVC Controller Builder factory with my Controller Builder factory on Application_Start event i.e.
protected void Application_Start()
{
IUnityContainer container = new UnityContainer();
//All container registrations ....
ControllerBuilder.Current.SetControllerFactory(new
UnityControllerFactory(container));
//Store reference of container in application object
HttpContext.Current.Application["Injector"] = container;
}
However I need instance of container to resolve dependencies at certain places where it is not possible to do constructor injection, for e.g. Application_AuthenticateRequest event. So as a fallback, I have stored a reference to the container in the Application object. I used this instance to resolve references.
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
var container = HttpContext.Current.Application["Injector"] as
IUnityContainer;
var service = container.Resolve<IService>();
}
Is it ok to store the container reference in application variable or is there any other recommended practice ?
I also know there is Property Injection. Can I use it in this scenario?
You should strive to prevent access to the container from within application code. Within the Composition Root however, it is typically okay to access the container directly, and it is often impossible to prevent this anyway. Your Application_AuthenticateRequest can be considered part of your Composition Root, so it is fine to access the container (and there is really no way around it).
You can however simplify the code to the following:
private static IUnityContainer container;
protected void Application_Start()
{
container = new UnityContainer();
...
}
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
var service = container.Resolve<IService>();
}
We have a custom UnityResolver, and in Application_Start(), we configure (via GlobalConfiguration.Configure([...]), but you could do otherwise I guess) the resolver this way :
public static void Register(HttpConfiguration config)
{
UnityContainer container = new UnityContainer();
// This contains our actual container registrations.
UnityRegistrer.Register(container);
// IoC for WebAPI
config.DependencyResolver = new UnityResolver(container);
// IoC for WebForms
HttpContext.Current.Application.SetContainer(container);
// IoC for MVC5
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// Configure other stuff like routes, tracing, error handling, authorization, etc.
}
I'm no expert in Web development at large, so maybe you want to tweak some stuff, but this has been working well for us.
I am working with a WPF based application and using Autofac to resolve the dependency of DbContext of Entityframework. I used the below code to register my data module.
public class DataModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<DataContext>()
.As<IDbContext>()
.WithParameter("nameOrConnectionString", "DefaultConnectionString")
.InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
}
}
This works fine while using in normal scenario but while using TPL, due to simultaneous calls to repository, it creates error stating that "ExecuteReader requires an open and available Connection. The connection's current state is open."
In web application, this can be resolved using InstancePerRequest to resolve dependency per request but in WPF I need to resolve this dependency per Thread request. Is there any way out for this?
I have review InstancePerRequest summary or autofac and it states that this method is used for Web request only:
// Summary:
// Share one instance of the component within the context of a single web/HTTP/API
// request. Only available for integration that supports per-request dependencies
// (e.g., MVC, Web API, web forms, etc.).
Update:
This is a simple async method that I used to get the data:
private async void OnLoadClientDetail()
{
long clientId = SelectedClient != null ? SelectedClient.Id : 0;
var listOfCollection = await _collectionService.GetCollectedCollectionAsync(clientId);
CollectionList = new ObservableCollection<CollectedCollection>(listOfCollection);
}
Here OnLoadClientDetail is bound to selection change event of a combobox. When user change the selection frequently then this method will be called multiple times. The _collectionService is injected in the viewmodel and has InstancePerLifetimeScope define. So how can I get different scope for all this calls?
As far as I can see, you share the _collectionService instance across the different event handlers by injecting it by Constructor Injection.
It probably better to use Method Injection here, so you'll get the instance per call, as you need, resolving it before method:
builder.Register(c =>
{
var result = new MyObjectType();
var dep = c.Resolve<TheDependency>();
result.SetTheDependency(dep);
return result;
});
I am attempting to set up DI on ActionFilters in ASP.NET WebAPI using Ninject. I followed the instructions here: https://github.com/ninject/Ninject.Web.WebApi/wiki/Dependency-injection-for-filters
I create my ActionFilter like so:
public class ApiAuthorizeFilter : AbstractActionFilter
{
private readonly IValidateApiTokenService _validateApiTokenService;
public ApiAuthorizeFilter(IValidateApiTokenService validateApiTokenService)
{
_validateApiTokenService = validateApiTokenService;
}
public override bool AllowMultiple => true;
public override void OnActionExecuting(HttpActionContext actionContext)
{
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
}
}
I configured like so:
kernel.BindHttpFilter<ApiAuthorizeFilter>(FilterScope.Controller);
My understanding based on the info at the above link is that the ActionFilter should then run for all Actions in all WebAPI controllers. However, I've set breakpoints at both overridden methods in the filter and it never gets hit. I have set a breakpoint at the configuration and can confirm that it is being executed.
What am I missing? I need this ActionFilter to run on all Actions in every ApiController in my project.
in your Startup Class
public void Configuration(IAppBuilder app)
{
var kernel = new StandardKernel();
// register IValidateApiTokenService
var config = new HttpConfiguration();
config.Filters.Add(new ApiAuthorizeFilter(kernel.Get<IValidateApiTokenService>());
}
The reason it doesn't work per say is because ActionFilters (or any filters for that matter) are created as singletons by the runtime (one instance forever on the app context) and in general any DI container has problems wiring up a object's transient and or disposable dependencies if that object is a singleton.
One solution to your problem would be to use the built in service locator like so:
DependencyResolver.Current.GetService(typeof(IValidateApiTokenService));
I don't personally use Ninject for my DI needs but if the above doesn't work it probably needs some wiring up in the DI startup or use a integration package like this one:
https://github.com/ninject/ninject.web.mvc/wiki/MVC3
I never worked on Ninject, I worked on Unity. With my experience of working on Unity I will try to shed some light on the issue.
I am not sure what is the purpose of _validateApiTokenService, but what I can observer from the above code is that you have to configure to bind the dependency to the implementation IValidateApiTokenService. Along with the following code
kernel.BindHttpFilter<ApiAuthorizeFilter>(FilterScope.Controller);
you may have to have some thing like
kernel.Bind<IValidateApiTokenService>().To<ValidateApiTokenService>();
or
kernel.Bind<IValidateApiTokenService>.To<ValidateApiTokenService>().InSingletonScope();
if it is to be in Singleton scope.
The simple injector documentation provides great examples on how to setup the container for WebRequest, Web API, WCF, ... but the examples are specific to one technology/lifestyle at a time. Our web application uses most of them together!
It is not clear to me how to configure the container to work with several lifestyles.
Let's say I have a MVC project with Web API. I have the following objects:
MyDbContext : My entity code first db context
IMyDataProvider implemented by MyDataProvider : Contains query logic and uses MyDbContext
MyController : MVC controller that uses IMyDataProvider
MyApiController : WebApi controller that uses IMyDataProvider
Should I create and configure one container for each type of lifestyle ?
When I register everything with RegisterPerWebRequest<T> is works in both types of controllers. Is this safe ? Or will I run into trouble when using async/await in a Web API controller?
What is the best configuration when I have both MVC and Web API controllers who get injected the same instances ?
Should I use a hybrid lifestyle ?
Now to complicate things... our application also uses background tasks and SignalR.
Both of these will sometimes occur outside of a WebRequest and need access to the same objects as described above.
The best solution would be to use a Lifetime scope ?
Would I need to create a new container for that lifestyle? or can I reuse/reconfigure my MVC/Web API container ?
Is there a triple lifestyle?
I have to say, I stumble on a similar scenario some time ago, I ended up by sharing my configuration over my web API and signalR, but you need to implement a custom lifestyle for signalR since it's not based on web request.
specially in signalR you'll find some issues handling per-web-request dependencies in a Hub some of them are going to be null like httpContext.Current among others.
The solution:
You need a hybrid lifestyle between WebRequestLifestlye and either Lifestyle.Transient, Lifestyle.Singleton, or LifetimeScopeLifestyle. I ended up I finished using the decorator pattern, you may read this post and this other post.
my decorator
public class CommandLifetimeScopeDecorator<T> : ICommandHandler<T>
{
private readonly Func<ICommandHandler<T>> _handlerFactory;
private readonly Container _container;
public CommandLifetimeScopeDecorator(
Func<ICommandHandler<T>> handlerFactory, Container container)
{
_handlerFactory = handlerFactory;
_container = container;
}
public void Handle(T command)
{
using (_container.BeginLifetimeScope())
{
var handler = _handlerFactory(); // resolve scoped dependencies
handler.Handle(command);
}
}
}
public interface ICommandHandler<in T>
{
void Handle(T command);
}
I managed the dependencies using a hub activator for signalR
public class MyHubActivator : IHubActivator
{
private readonly Container _container;
public MyHubActivator(Container container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
return _container.GetInstance(descriptor.HubType) as IHub;
}
}
a composite root file which is where you are going to handle your dependencies
public CompositRoot(Container container)
{
_container = container;
}
public container Configure()
{
// _container.Registerall container dependencies
return _container;
}
then share your composite root configuration when you are bootstrapping your app
var compositRoot = new CompositRoot(simpleInjector.Container); //simple injector instance
compositRoot.Configure();
For signalR
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => new MyHubActivator(compositRoot));
and you may reuse your configuration among other projects!
my two cents
hope that helps!
Usually you don't need to have one container per lifestyle; In general you want to have one container instance per AppDomain. However, mixing Web API in the same project with MVC is from an architectural point of view a horrible idea IMO (as explained here, here, and here). So in case you are separating those parts into their own architectural blocks, you will already have less problems already.
But in case you are running MVC and Web API in the same project, this basically means that you will always be using Web API. The WebApiRequestLifestyle was explicitly built to work:
well both inside and outside of IIS. i.e. It can function in a
self-hosted Web API project where there is no HttpContext.Current.
(source)
In general, it is safe to use the WebRequestLifestyle in case you are only running in IIS when you have no intention to spin of parallel operations using ConfigureAwait(false) (which should be really rare IMO) as explained here.
So in the case you are still mixing Web API with MVC in the same project, there's no reason to use a hybrid lifestyle; you can simply use the same lifestyle. For doing background processing you might however need to build a hybrid lifestyle, but it every scenario needs a different hybrid. However, hybrids can be stacked up and you can easily create a 'triple lifestyle' if needed.
Since you want to do background processing with SignalR, you need to decide in what type of scoped lifestyle to run those background operations. The most obvious lifestyle is the LifetimeScopeLifestyle and this means you should make your scoped registrations using the following scoped lifestyle:
var hybridLifestyle = Lifestyle.CreateHybrid(
lifestyleSelector: () => HttpContext.Current != null,
trueLifestyle: new WebRequestLifestyle(),
falseLifestyle: new LifetimeScopeLifestyle());
A lifetime scope however needs to be started explicitly (as were the web request scope gets started implicitly for you if you include the SimpleInjector.Integration.Web.dll in your web application). How to do this depends on your design, but this q/a about SignalR might point you in the right direction.