2017-07-20 3 views
0

J'utilise Autofac dans mon projet et pour la plupart cela fonctionne très bien. Il y a quelque temps, je avais besoin d'avoir accès à l'utilisateur actuel et on m'a dit la meilleure façon de le faire était de créer une classe wrapper comme ceci:Autofac, les utilisateurs et la journalisation

public class PrincipalProvider : IPrincipalProvider 
{ 
    public IPrincipal User => HttpContext.Current?.User; 
} 

Cela a fonctionné sans aucun problème dans ma demande. J'ai maintenant un nouveau fournisseur qui ressemble à ceci:

public class WmsProvider : IWmsProvider 
{ 
    private readonly Lazy<ILogProvider> _logProvider; 
    private readonly Lazy<IMessageProvider> _messageProvider; 

    private readonly CormarConfig _config; 
    private readonly ClaimsIdentity _identity; 

    public WmsProvider(IPrincipalProvider principalProvider, Lazy<ILogProvider> logProvider, Lazy<IMessageProvider> messageProvider) 
    { 
     _messageProvider = messageProvider; 
     _logProvider = logProvider; 

     _identity = (ClaimsIdentity)principalProvider.User.Identity; 
    } 

    /// <summary> 
    /// Sends the order to WMS 
    /// </summary> 
    /// <param name="model">The order model</param> 
    public async Task SendAsync(OrderViewModel model) 
    { 
     var request = WmsFactory.Create(model); 
     await _logProvider.Value.TraceAsync($"This is a test", _identity); 
     await _messageProvider.Value.CreateAsync(request, model.OrderNumber, MessageType.Wms, "ORD", Method.POST, null); 
    } 
} 

(je dépouillé le reste du code pour la brièveté)

Dans ce cas, l'utilisateur est nulle et jette une erreur (Object instance non trouvée). Mais j'ai une autre classe avec un constructeur similaire:

public OrderProvider(CormarConfig config, IOrderService orderSerivce, IPrincipalProvider principalProvider, Lazy<IAccountProvider> accountProvider, Lazy<ICollectionManagerProvider> collectionManagerProvider, Lazy<IEmailProvider> emailProvider, Lazy<IJournalProvider> journalProvider, Lazy<IOrderLineProvider> orderLineProvider, Lazy<IStockProvider> stockProvider, Lazy<webServices> webService, Lazy<ITroposOrderLineService> troposOrderLineService, Lazy<ITroposOrderService> troposOrderService, Lazy<ITroposUnitOfWork> troposUnitOfWork, Lazy<IWmsProvider> wmsProvider) 
    { 
     //Assign our config 
     _config = config; 

     // Add our services to our class 
     _connectionType = config.ConnectionType; 
     _orderService = orderSerivce; 

     // Add our providers to our class 
     _identity = (ClaimsIdentity)principalProvider.User.Identity; 

     // Add our optional providers 
     _accountProvider = accountProvider; 
     _collectionManagerProvider = collectionManagerProvider; 
     _emailProvider = emailProvider; 
     _journalProvider = journalProvider; 
     _orderLineProvider = orderLineProvider; 
     _stockProvider = stockProvider; 
     _webService = webService; 
     _wmsProvider = wmsProvider; 
     _troposOrderLineService = troposOrderLineService; 
     _troposOrderService = troposOrderService; 
     _troposUnitOfWork = troposUnitOfWork; 
    } 

Et cela fonctionne très bien. Les deux sont enregistrés de la même façon dans mon Module:

builder.RegisterType<OrderProvider>().As<IOrderProvider>().InstancePerRequest(); 
builder.RegisterType<WmsProvider>().As<IWmsProvider>().InstancePerRequest(); 

builder.RegisterType<PrincipalProvider>().As<IPrincipalProvider>(); 

Une chose à noter, est que WmsProvider est injecté dans OrderProvider, il est donc pas dans le contrôleur directement injecté. Le constructeur du contrôleur ressemble à ceci:

public OrdersController(IOrderProvider provider) 
{ 
    _provider = provider; 
} 

Ceci pourrait être l'origine du problème. Dans une personne à charge, le contexte n'est-il pas disponible? Si ce n'est pas ce qui est la solution? Y a-t-il un moyen d'arriver au contexte de l'enfant?

Toute aide serait appréciée.

+0

'Dans ce cas, l'utilisateur est null et génère une erreur (instance d'objet introuvable). Quelle ligne renvoie cette exception? Quel est le type de cette exception? – mjwills

Répondre

0

J'ai compris cela. Ce fut comme je le disais, le contexte n'était pas disponible dans les classes imbriquées, afin de résoudre ce problème je l'ai changé l'enregistrement de la PrincipalProvider à l'instance par requête:

builder.RegisterType<PrincipalProvider>().As<IPrincipalProvider>().InstancePerRequest(); 

Et je changé le PrincipalProvider ressembler à ceci:

public class PrincipalProvider : IPrincipalProvider 
{ 

    // Readonly fields 
    private readonly HttpContext _current; 

    /// <summary> 
    /// Default constructor 
    /// </summary> 
    public PrincipalProvider() 
    { 
     _current = HttpContext.Current; 
    } 

    /// <summary> 
    /// Gets the current user 
    /// </summary> 
    public IPrincipal User => _current?.User; 
} 

Et cela a résolu mon problème.