Background tasks with .NET CORE Lifetime and DI injection - asp.net-core

I want to use background tasks in asp.net core.
I found helpful documentation https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-6.0&tabs=visual-studio
I wonder why their lifetime apparently is scoped: Hosted service that activates a scoped service. The scoped service can use dependency injection (DI).
What is a scope in this context?
For web applications, a scoped lifetime indicates that services are created once per client request (connection). Register scoped services with AddScoped.
In apps that process requests, scoped services are disposed at the end of the request.
While I do understand what that means for e.g a standard http get request to an api,
I do not understand the meaning for a background worker.
Imho it would make more sense to have a singleton backgroundworker. I certainly do not want to have multiple instances running at a time in my application.
Another thing is DI in background workers which apparently differs fron standard services:
To use scoped services within a BackgroundService, create a scope. No scope is created for a hosted service by default.
I cannot confirm that:
services.AddHostedService(x => new DataPersister(x.GetRequiredService<IAsyncDocumentSession>(), x.GetRequiredService<ILogger>()));
seems to work just fine.

You have to read the sentence “Hosted service that activates a scoped service” within its full context:
This article provides three hosted service examples:
Background task that runs on a timer.
Hosted service that activates a scoped service. The scoped service can use dependency injection (DI).
Queued background tasks that run sequentially.
(from “Background tasks with hosted services”, emphasis mine)
So it is not the case that hosted services have a scoped lifetime. All hosted services added using AddHostedService() are actually added with a singleton lifetime, ensuring that there will only ever be a single instance of it.
What the article refers to is the situation when you need to consume a scoped service, like a database connection, within a hosted service. Since you cannot inject scoped dependencies into a singleton service, you will need a different solution there. And the solution usually involves having the singleton service (the hosted service in this case) create a service scope itself from which it can then retrieve the scoped dependency.
I went into more details about the service scopes in this recent answer to a similar question if you are interested.

Related

Blazor Serverside singleton service, Changes in one browser are reflected in another, when loading the same page

In Blazor serverside, I created a shopping cart in a website using a singleton service, And I expected different users have different instances of this service, But when I load the website in two types of browsers, Adding an Item to cart is reflected in another browser, And even I can see the change, (I also used a singleton service for each user's data and the site is published to the web). Is this the correct behaviour for singleton services and how to solve it?
This is the expected behavior of a singleton service. In your case you should use the scoped service.
Transient lifetime services (AddTransient) are created each time they're requested from the service container. This lifetime works best for lightweight, stateless services.
Scoped lifetime services (AddScoped) are created once per client request (connection).
Singleton lifetime services (AddSingleton) are created the first time they're requested (or when Startup.ConfigureServices is run and an instance is specified with the service registration). Every subsequent request uses the same instance. If the app requires singleton behavior, allowing the service container to manage the service's lifetime is recommended. Don't implement the singleton design pattern and provide user code to manage the object's lifetime in the class.
Taken from the Microsoft Docs.
Also, note that lifetimes work differently in Blazor WebAssembly and Blazor Server. See Microsoft Docs.

Service Bus in ASP.NET Core

I would like my ASP.NET Core application to send messages to a Azure Service Bus.
In Microsoft's article Best Practices for performance improvements using Service Bus Messaging they argue that you should re-use instances of clients.
It is recommended that you do not close messaging factories or queue, topic, and subscription clients after you send a message, and then re-create them when you send the next message.
So I take that as I should not instantiate a new instance of the client (TopicClient or QueueClient) inside my controller using the new keyword.
I guess that I should use dependency injection in ASP.NET Core.
Should I directly inject a TopicClient/QueueClient or should I create an own class that wraps an instance of the client and expose a SendAsync method?
When registering the service with dependency injector should I register it as a singleton?
We did it with a wrapper class that is then returning the TopicClient/QueueClient and registered it as a singleton and found no big issues with this approach.
We based our approach on this example provided by Microsoft eshopOnContainers.
The example code for this functionality is found in this file. They than register this class as singleton in Startup.cs in the services where they require ServiceBus.

OperationContext in State Machine Workflows (WF 4.5)

So what I'm struggling with is the following scenario.
I'm trying to integrate DI (Autofac) in a xamlx workflow service.
Since such a service is merely a WCF hosted service, I thought I could just look at Autofac's WCF integration implementation and adapt that so it can be used with a WorkflowServiceHost(Factory).
And while I managed to do this (adding an InstanceContextInitializer which puts an IExtension on the current OperationContext to start a new LifetimeScope for the WCF request) and successfully tested it with a simple Sequential Workflow, this doesn't work with a State Machine Workflow!
Well, it does work in the first state of that workflow, but after transitioning to the following state, the OperationContext is gone.
So my questing is, is anybody out there doing something similar? To have a lifetime scope per WCF request to a xamlx state machine workflow service?
For now I guess I'm going to have to go with a lifetime scope per Activity to have some kind of control over my resovled objects from the container..

Is there a way to force IIS to invoke CustomServiceHost?

All,
I have developed a WCF Web Service and hosted it in IIS7.5. The service behavior is instanceContextMode=InstanceContextMode.PerSession and hence IIS creates an service instance during the first requests and creates as many instances as the number of requests.
But there is a requirement to cache some of the application data upfront before the service is invoked ie., similar to static initialization.
I don't want to disturb the service behavior attributes but want to achieve the static initialization.
I did try to use CustomServiceFactory and take up the load of creating service factory instances myself. But looks like the IIS will create the service factory as well during first request or I am not sure on this part.
So, I would like to know how to create the service instance / service factory instance when the application is deployed in IIS or during IIS restart?
Any help is much appreciated!
We are using the auto-start feature of AppFabric to initialize the services on application startup/app pool recycle. It invokes each service inside the application once during application start.

What is the lifecycle of an IIS-hosted (http) WCF service?

I have a dependency injection container setup in my application and I'm thinking that composing the container every time a WCF service request comes in is going to be inefficient.
Can somebody explain to me, for an http/IIS hosted WCF service, what the lifecycle of the service is? If I can figure this out, I can make an educated decision on where the container is to be stored, instantiated, destroyed, etc.
If your InstanceContextMode is PerCall, the service class will be created from scratch for every incoming request, and then disposed of when it's done.
If your InstanceContextMode is PerSession, the service class will be created and used to service one given client for the duration of the session (or until an "InactivityTimeout" is encountered, or an error occurs).
If your InstanceContextMode is Single (singleton), the service class will be created when the first request comes in and will stay in memory as long as requests keep coming in, as long as no error occurs and no inactivityTimeout is reached.
So, there you have it! Of course, the concurrency mode (for PerSession and Single services) will also come into play to make things just a tad more "interesting"
As you mention that you were trying to integrate WCF service instantiation with a dependency injection container, I'd just like to say that I've had a very positive experience using the Castle WCF Integration Facility to do just that.
It's specific to the Castle Windsor dependency injection container but with it being open source you can look inside and understand some of the challenges and solutions provided.
It depends on your ServiceBehavour.
Specifically this and this.