I am getting the above error and I realize why, but the odd behavior I see that it only happens in our Dev environment and not in for example our staging or Production environment and it is the exact same code.
In the startup there is :
services.AddSingleton<ExcahngeService>();
services.AddScoped<ITradingService, TradingService>();
This throws the error:
"cannot consume a scoped service from singleton"
but it only happens in a development environment and it is the same code in all environments
Could this be due to a timing issue, where the environment is slower ?
Scoped instance lifetime is limited, It is only available per request. So you are consuming an instance from Scoped service into Singleton and the error throws because of the scoped service is disposed. Either make both Singleton or Scoped
As Microsoft best practice you should create new scope and get scoped service from ServiceProvider
https://learn.microsoft.com/en-us/dotnet/core/extensions/scoped-service
Related
I have an issue with Hangfire, most likely because of my ignorance about some topics.
I have a host/plugins infrastructure, where each plugin is loaded at runtime and it register its interfaces.
public void ConfigureServices(IServiceCollection services, IConfigurationRoot Configuration)
{
services.AddTransient<IManager, Manager>();
services.AddTransient<IAnotherManager, AnotherManager>();
this.AddControllers(services);
}
Some plugin may add jobs using Hangfire, which are also set during runtime
public void ScheduleJobs()
{
RecurringJob.AddOrUpdate<IManager>(n => n.SayHello(), Cron.Monthly);
}
The issue I have is, while any service registered directly in the host is correctly resolved in hangfire,
all the interfaces (ex IManager) that are defined in external assemblies aren't found.
I added a customer JobActivator where I'm passing the IServiceCollection and I can actually see that those external services are registered (and I can use them anywhere else but from Hangfire), but still
in the JobActivator, when Hangfire tries to resolve the external service, it fails.
public override object ActivateJob(Type type)
{
// _serviceCollection contains the IManager service
var _provider = _serviceCollection.BuildServiceProvider();
// this will throw an Exception => No service for type '[...].IManager' has been registered.
var implementation = _provider.GetRequiredService(type);
return implementation;
}
In the same example, if I use the Default JobActivator, then the exception I get is System.MissingMethodException: Cannot create an instance of an interface.
I could enqueue the job using the Class instead of the Interface, but that's not the point and anyway if the Class has services injected, those will not be resolved as well.
What am I missing?
The problem has been solved. The solution is to add a specific IoC Container for hangfire. I used Unity. In that way dependencies are resolved correctly.
Thanks Matteo for making it clear that HF requires its own IoC container. This link makes the point too:
Hangfire needs to have it's own container with dependencies registered independently of the global UnityContainer. The reason for this is twofold; Hangfire's dependencies need to be registered with the PerResolveLifetimeManager lifetime manager. This is so that you don't get concurrency issues between workers that have resolved a dependency to the same instance. For example; with the normal HierarchicalLifetimeManager, two workers needing the same repository dependency may resolve to the same instance and share a common db context. The workers are meant to each have their own db contexts. Secondly, when the OWIN bootstrapper is run, the global UnityContainer may or may not be initialised yet and Hangfire is unable to take in a reference to the container. So giving Hangfire it's own managed container is a clear separation of purpose and behaviour in how our dependencies are resolved.
I would like to test certain conditions on Startup of my ASP.Net Core 2.0 application. For example if my database server or other is running correctly. This is especially helpful for things that will only be instantiated after a request (like my repository).
Currently I have to do this request manually, but I would like to have my application fail early. At what moment and in what place is such a test recommended?
The Startup class is responsible for setting up your server, making it the perfect candidate for setting up one-time initialization stuff for your application.
You usually have two main methods in Startup: ConfigureServices and Configure. The former runs very early and is responsible for setting up the application services, dependencies and configuration. So you cannot use it to actually perform real work, especially since the dependency injection container is not ready yet.
However, the Configure method is different: While its main purpose is to set up the application middleware pipeline, the components that will later serve requests, you are able to fully use your dependencies here, making it possible to already do more extensive things here. So you could make your calls directly here.
It’s important to understand that Configure still runs rather early, way before your server is actually ready to serve requests. So if your initialization depends on the actual server being around already, you should probably further delay the execution.
The proper solution is likely to hook into the application lifecycle using IApplicationLifetime. This type basically offers you a way to register callbacks that are executed during the application lifecycle. In your case, you would be interested in the ApplicationStarted event which runs when the server just completed its setup phase and is now ready to serve requests. So basically the perfect idle moment to run some additional initialization.
In order to respond to a lifetime event, you need to register your handler inside the Configure method:
public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime)
{
// other…
// register lifetime event
applicationLifetime.ApplicationStarted.Register(InitializeApplication);
}
public void InitializeApplication()
{
// do stuff
}
One final note: Apparently, there is currently an open bug that prevents lifetime events from firing when hosting on IIS. In that case, executing your code directly in Configure is probably the best alternative.
I can't seem to get the Castle Windsor Integration working for Mass Transit over RabbitMQ. Everything was working fine until I introduced Windsor into the picture. I referenced Castle.Windsor 3.2 and MassTransit.WindsorIntegration 2.9 and configured the container for use within my application. I'm registering the MassTransit Consumers via:
Container.Register(..., Types.FromThisAssembly().BasedOn<IConsumer>());
When I debug and inspect the container after this line is ran, I can see that it successfully registered all of the consumers along with all of my other components. I then have the following code to initialize and register the service bus:
var serviceBus = ServiceBusFactory.New(sbc =>
{
sbc.UseRabbitMq();
sbc.ReceiveFrom(Config.ServiceBusEndpoint);
sbc.Subscribe(sc => sc.LoadFrom(Container));
});
Container.Register(Component.For<IServiceBus>().Instance(serviceBus));
I am using the LoadFrom(IWindsorContainer container) extension method provided by MassTransit.WindsorIntegration.
All of the examples I've found so far stop here and indicate that this is all you should have to do. Unfortunately for me my Consumers are never being called and messages are just piling up in the queue (eventually timing out and going to error queue). The fact that messages are showing up in the Consumer queue at all (+ I see a single consumer bound to the queue via the RabbitMQ Admin Tool) indicates to me that the consumers are probably being subscribed properly - so I'm not sure where the problem lies.
I added NLog logging for Windsor and MassTransit but no errors are showing up in the logs. I'm not sure how I should proceed troubleshooting at this point. Any ideas?
Also, this application is currently just a console application using Topshelf for development. Ultimately it will be installed as a Windows Service. Not sure if that is relevant or not but I thought I'd mention it just in case.
UPDATE
As a test I created a very simple Consumer with a parameter-less constructor for processing a very simple test message. This Consumer is successfully called! The "real" Consumers however have dependencies that need to be injected into them via the constructor. I was hoping the Container would resolve these but apparently it's having some sort of trouble. Weird that nothing is showing up in the logs about it. Stay tuned...
Okay I figured it out. Somewhere along the way when I was adding/removing NuGet packages I somehow managed to delete a reference to a DLL (ServiceStack.Text.dll) that one of my components needed (RedisClientsManager).
I started the debugger, let all my components get registered then popped open the Immediate Window and attempted to resolve each component one by one (by calling container.Resolve<RegisteredType>()) until I found the one that threw the exception when I attempted to resolve it.
The Exception message from Windsor at that point told me exactly what the problem was. I'm a little lost as to why this wasn't being logged or why the Exception was not raised when the container itself attempted to resolve it. Anyhow, moral of the story is make sure your components resolve.
is this possible somehow? Following scenario:
statelesse local EJB with name A
singleton startup EJB with name B
B contains a reference to A
I tried but my application server (WAS) fails on application startup with the error that A was not found. The console log also makes clear that A was not started at the moment the B is loaded but some other stateless EJBs are started before B. Making A also a singleton EJB and letting B depond on A via annotation #DependsOn({"A"}) produced an error, too, stating that dependent bean A was not found. Using A in a web module works fine.
Any ideas what' I do wrong? Thx for any help!
Steffen Harbich
If A is in a different module/application as B, then you need to ensure that the module of A is configured to start before the module of B. You can either use initialize-in-order in application.xml, or use module starting weights in the admin console.
I am using the WCF facility for a service hosted in WAS (net.tcp binding in iis7) and experiencing a weird issue only upon a cold application startup (i.e. not already running).
The following statement should be executed upon first instantiation of my container.
DefaultServiceHostFactory.RegisterContainer(c.Kernel);
When the service is requested, I get the following exception in my WCF tracefile
Kernel was null, did you forgot to call DefaultServiceHostFactory.RegisterContainer()
The issue appears to be that the ServiceHostFactory is attempting to create an instance of the service's host before my container has been created.
Note:
This exception is happening BEFORE the Application_Start is executed
If the application is running (and the container has been initialised) then the service will operate as expected. The application can be started by going to the appropriate IIS site over HTTP or starting a debugging session from Visual Studio.
Steps to recreate issue
Issue a IISReset to shutdown all IIS app pools.
Call the service in question
WCF tracing spits out:
System.ServiceModel.ServiceActivationException: The service '/abcd.svc' cannot be activated due to an exception during compilation. The exception message is: Exception has been thrown by the target of an invocation.. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentNullException: Kernel was null, did you forgot to call DefaultServiceHostFactory.RegisterContainer() ?
Parameter name: kernel
at Castle.Facilities.WcfIntegration.WindsorServiceHostFactory`1..ctor(IKernel kernel)
at Castle.Facilities.WcfIntegration.DefaultServiceHostFactory..ctor()
The problem is that global.asax and all its methods are related only to HTTP processing. Btw. class in global.asax is derived from HttpApplication which should make this pretty clear. Once you host application in WAS (which is case of net.tcp based binding) you can't use these methods. Try to use something like AppInitialize.