Hezye
Hezye

Reputation: 1551

Configure injected services with information available in runtime

I've been trying to modify injected services with values available from authenticated users.

Using the built-in DI container, I added the required service with Scoped lifetime.

services.AddScoped<ITodoRepository, TodoRepository>();

Then registered a custom middleware between authorization and MVC middlewares to modify the repository with user specific information.

// Configure authorization middleware

app.Use(async (context, next) =>
{
     var todoRepository = context.ApplicationServices.GetRequiredService<ITodoRepository>();
     todoRepository.UserStoreId = context.User.GetUserStoreId();
     await next.Invoke();
 });

 // Configure MVC middleware

When the program execute a request, the injected repository within my controller does not presist the saved value.

Am i doing something wrong? From my understanding, scoped objects are saved within request.

Also, is there another way to achieve this?

Upvotes: 1

Views: 225

Answers (2)

Hezye
Hezye

Reputation: 1551

Am i doing something wrong? From my understanding, scoped objects are saved within request.

I was able to fix the issue by replacing

context.ApplicationServices.GetRequiredService<ITodoRepository>();

with

context.RequestServices.GetRequiredService<ITodoRepository>();

Upvotes: 0

Tseng
Tseng

Reputation: 64150

You can create your own service, i.e. IAuthenticatedUserService/AutheticatedUserService.

Into it, you inject IHttpContextAccessor.

public interface IAuthenticatedUserService
{
    ClaimsPrincipal User { get; }
}

Then you inject the IAuthenticatedUserService into your repository, where you can access the logged-in user.

Of course you could also directly inject IHttpContextAccessor into your repository and access httpContextAccessor.HttpContext.User within it, but since repositories are usually defined in their own assembly, you'd also need to reference the Microsoft.AspNetCore.Http.Abstractions package from it which would cause a tight(er) coupling.

But if you don't mind this kind of coupling, just inject the IHttpContextAccessor into your repository, they are supposed to be scoped (=per request) or transient anyways.

P.S. don't forget the Dependency Injection/Inversion of Control mantra: "Don't call us, we call you". You have attempted to call "us" (the repository) to set a value.

Upvotes: 2

Related Questions