Search code examples
c#asp.net-web-apiautofac

Autofac Getting the current identity


I have a Service and virtually every method requires the current user to execute. Before I started using autofac I basically created a public property like this:

private IOrderProvider _orderProvider;

public IOrderProvider OrderProvider => _orderProvider ?? (_orderProvider = new OrderProvider((ClaimsIdentity)User.Identity));

Because this was a public property on the controller, it would have access to the User. Now using autofac I register my Service in the StartupConfig. Naturally I don't have access to the User there.

Is there a way to inject the current user into the OrderProvider constructor, or another way to get at it?


Solution

  • The user principal can be accessed through the HttpContext.Current.User. How ever tightly coupling code to HttpContext is frowned upon as it is not very unit test friendly. so create a service that exposes what you want.

    using System.Security.Principal;
    public interface IPrincipalProvider
    {
        IPrincipal User { get; }
    }
    

    An implementation in production can look like this.

    using System.Security.Principal;    
    public class DefaultPrincipalProvider : IPrincipalProvider
    {
        public IPrincipal User
        {
            get
            {
                return HttpContext.Current.User;
            }
        }
    } 
    

    With that done update the dependent class to use the abstraction

    public class OrderProvider : IOrderProvider
    {
        private readonly ClaimsIdentity identity;
        public OrderProvider(IPrincipalProvider provider) {
            identity = (ClaimsIdentity)provider.User.Identity;
        }
    }
    

    and then register the provider on startup as usual

    //...other code removed for brevity
    
    builder.RegisterType<DefaultPrincipalProvider>().As<IPrincipalProvider>();
    builder.RegisterType<OrderProvider>().As<IOrderProvider>();
    
    //...other code removed for brevity
    

    The service should get everything injected

    public class Service {
        private readonly IOrderProvider _orderProvider;
    
        public Service(IOrderProvider orderProvider) {
            _orderProvider = orderProvider;
        }
    
        public IOrderProvider OrderProvider => _orderProvider;
    }