10

I have a class that requires ApplicationUser (from ASP.NET Identity). The instance should be the current user.

public class SomeClass
{
    public SomeClass(ApplicationUser user)
    {

Currently, what I'm doing is I inject the current user from the Controller:

var currentUser = await _userManager.GetUserAsync(User);
var instance = new SomeClass(currentUser);

Now I want to use Dependency Injection provided by Microsoft. I can't figure out how am I going to add ApplicationUser to the services. It requires User which is a property of the Controller.

So how do you inject ApplicationUser (instance of the current user) via DI provided by Microsoft?

3
  • 2
    Generally, you're supposed to inject dependencies, not data. It's better to provide the desired context (the invoking user, in your case) upon calling each method (or explicitly by calling some Init(context)) so that the consumers of the type are more aware of the actual needs. Injecting the context automatically behind the scenes by the DI will advance your DI skills but may lead to inconsistencies in the future. Commented Apr 10, 2017 at 12:05
  • @haim770 thanks. I think I'm just being lazy by not wanting to provide it in every method call. The Init(context) you said may be an alternative, I wonder how do I enforce it to be called. Commented Apr 10, 2017 at 12:16
  • As @haim770 stated, prevent injecting runtime data into your components. For more details, please read this. Commented Apr 10, 2017 at 13:41

1 Answer 1

6

You can inject both UserManager<ApplicationUser> and IHttpContextAccessor to the constructor of your class, then:

public class SomeClass
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IHttpContextAccessor _context;
    public SomeClass(UserManager<ApplicationUser> userManager,IHttpContextAccessor context)
    {
        _userManager = userManager;
        _context = context;
    }

    public async Task DoSomethingWithUser() {
        var user = await _userManager.GetUserAsync(_context.HttpContext.User);
        // do stuff
    }
}

If you don't want to take direct dependency on IHttpContextAccessor but still want to use DI, you can create interface to access your user:

public interface IApplicationUserAccessor {
    Task<ApplicationUser> GetUser();
}

public class ApplicationUserAccessor : IApplicationUserAccessor {
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IHttpContextAccessor _context;
    public ApplicationUserAccessor(UserManager<ApplicationUser> userManager, IHttpContextAccessor context) {
        _userManager = userManager;
        _context = context;
    }

    public Task<ApplicationUser> GetUser() {
        return _userManager.GetUserAsync(_context.HttpContext.User);
    }
}

Then register it in DI container and inject into SomeClass:

public class SomeClass
{
    private readonly IApplicationUserAccessor _userAccessor;
    public SomeClass(IApplicationUserAccessor userAccessor)
    {
        _userAcccessor = userAccessor;
    }

    public async Task DoSomethingWithUser() {
        var user = await _userAccessor.GetUser();
        // do stuff
    }
}

Other options include (as mentioned in comments) not inject anything but require passing ApplicationUser as argument to the methods which require it (good option) and require initialization before using any methods with special Initialize(user) method (not so good, because you cannot be sure this method is called before using other methods).

Sign up to request clarification or add additional context in comments.

9 Comments

In case SomeClass is declared in a different assembly, this will enforce it to depend on Microsoft.AspNetCore.Http
@haim770 you are right, it's better to not inject ApplicationUser at all but just accept it as a parameter to the method. However if OP wants to get it via DI still - this is a possible option.
My thoughts exactly, this is an alternative but don't want to be tied to HttpContext
@dpp you can avoid that, and you can even inject ApplicationUser itself - but I would advice against doing that. Doing heavy things that might throw during dependency resolution is not a good idea. If you want to go via injection route - create some IApplicationUserAccessor with Task<ApplicationUser> GetUser() method and inject this one into your class.
@dpp I've updated answer with an example with IApplicationUserAccessor.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.