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?
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;
}