vinayak hegde
vinayak hegde

Reputation: 2222

What is the meaning of "When using a scoped service, inject the service into the Invoke or InvokeAsync"?

I was reading the MS doc about DI in .Net Core.

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2

I came across the line

"Warning

When using a scoped service in a middleware, inject the service into the Invoke or InvokeAsync method. Don't inject via constructor injection because it forces the service to behave like a singleton."

Anyone, please explain what is the meaning of this?

Then one of the most voted answer here uses constructor DI injection for scoped service. AddTransient, AddScoped and AddSingleton Services Differences?

Upvotes: 5

Views: 2981

Answers (2)

Ryan
Ryan

Reputation: 20116

This is documented in ASP.NET Core Middleware: Per-request dependencies.

Because middleware is constructed at app startup, not per-request, scoped lifetime services used by middleware constructors aren't shared with other dependency-injected types during each request. If you must share a scoped service between your middleware and other types, add these services to the Invoke method's signature. The Invoke method can accept additional parameters that are populated by DI:

public class CustomMiddleware
{
private readonly RequestDelegate _next;

public CustomMiddleware(RequestDelegate next)
{
    _next = next;
}

// IMyScopedService is injected into Invoke
public async Task Invoke(HttpContext httpContext, IMyScopedService svc)
{
    svc.MyProperty = 1000;
    await _next(httpContext);
}
}

Upvotes: 6

juunas
juunas

Reputation: 58733

This is quite an important thing. Your middleware class is instantiated only once, i.e. its constructor only runs once. If you have a dependency with lifetime of scoped or transient, it is meant to be shorter-lived. If you require such a dependency via the constructor, your middleware is dependent on a service with a shorter lifetime. The DI container can dispose the service after a request is done, leaving your middleware with a service which no longer works.

By requesting it at runtime in the Invoke/InvokeAsync function, you are able to use transient and scoped dependencies. Singletons can be required in the constructor, since those have the same lifetime as the middleware.

Upvotes: 4

Related Questions