Search code examples
c#dependency-injectionasp.net-core-6.0userprincipal

How to inject IPrincipal into a class


I have a class where I need to access IPrincipal because I will save some user information in a database from that class.

To inject it, I added this in Program.cs file:

builder.Services.AddScoped<IPrincipal>(
    (sp) => sp.GetService<IHttpContextAccessor>().HttpContext.User
);

With that, I receive a warning about IHttpContextAccessor telling that I need to use it with caution because it relies on AsyncLocal, and second, other warnings are shown telling I need to dereference GetService and HttpContext.

How can I do that properly in .NET Core 6?

enter image description here


Solution

  • I receive a warning ... telling that I need to use it with caution because it relies

    No, it is not the warning which is telling that, the caution comes from the remarks in the interface documentation which you see when you mouse over the interface definition.

    The warning you are getting is about dereferencing of a possibly null reference (some docs).

    warning CS8602: Dereference of a possibly null reference.

    The issue is that GetService can return null, and IHttpContextAccessor.HttpContext can be null also which is caught by compiler (see nullable references types). The proper workaround would be to extract corresonding abstraction and register/resolve it:

    public interface IPrincipalProvider
    {
        IPrincipal? Principal { get; }
    }
    
    public class PrincipalProvider : IPrincipalProvider
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
    
        public PrincipalProvider(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }
    
        public IPrincipal? Principal => _httpContextAccessor.HttpContext?.User;
    }
    
    builder.Services.AddScoped<IPrincipalProvider, PrincipalProvider>();