whale70
whale70

Reputation: 375

How to do DI for non-request bound code in ASP.NET Core?

We're all being taught to use Dependency-Injection for coding in ASP.NET Core applications, but all of the examples I've seen so far that related to the retrieval of services via DI relate to situations where the method that has the service reference injected is strictly bound to a specific HTTP request (HttpContext) (e.g. MVC controllers, Routing delegates).

Service location is warned against as an anti-pattern, but I'm not sure on how to obtain a proper service (e.g. DbContext) reference via DI in code that is not bound a specific HTTP request, e.g. code that has to respond to messages arriving over a websocket.

Although the websocket itself is set-up initially with a specific HTTP request, messages will get responses over potentially a long lifetime of the websocket (as long as the user web session lasts). The server should not reserve/waste a DbContext/DB connection over this entire lifetime (this would result in exhaustion quickly), but rather obtain a DB connection temporarily when a message arrives and requires a response; discarding the DbContext/connection immediately afterwards - while the original HTTP request that set-up the websocket in the very beginning of the user-session technically is still there.

I haven't been able to find anything else but using:

httpContext.RequestServices.GetService(typeof(<MyNeededDbContext>)

This way I use the initial httpContext (obtained via DI when the websocket was set up), but at multiple times after that whenever a websocket message needs a response I can request a transient service object (a DbContext in this example), that may be recycled or pooled after the message response is complete, but while the original httpContext is very much still alive.

Anyone aware of a better approach?

Upvotes: 0

Views: 392

Answers (1)

Jeremy Lakeman
Jeremy Lakeman

Reputation: 11110

You can create a new service scope to manage the lifetime of services yourself;

IServiceProvider provider = ...;
using (var scope = provider.CreateScope())
{
    var context = scope.ServiceProvider.GetService<MyNeededDbContext>();
    ...
}

Upvotes: 1

Related Questions