10

Seguendo il consiglio che ho ricevuto in questo thread [Ninject UOW pattern, new ConnectionString after user is authenticated ora capisco che non dovrei usare la seguente riga ...Come NON utente DependencyResolver.Current.GetService (...) in questa situazione/

var applicationConfiguration = 
      (IApplicationConfiguration) 
       DependencyResolver.Current.GetService(typeof(IApplicationConfiguration)); 

... come localizzatore di servizio è un anti-pattern.

Ma nel caso della seguente procedura come posso istanziare il mio oggetto concreto che implementa "IApplicationConfiguration" in modo che posso usare l'oggetto per ottenere il nome del ruolo utente sconosciuto, o usarlo per assegnare al "ApplicationConfiguration "proprietà del mio principio?

Codice Global.asax

public class MvcApplication : NinjectHttpApplication 
{ 
    /// <summary> 
    /// Handles the PostAuthenticateRequest event of the Application control. 
    /// </summary> 
    /// <param name="sender">The source of the event.</param> 
    /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> 
    protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) 
    { 
     String[] roles; 
     var applicationConfiguration = 
      (IApplicationConfiguration) 
       DependencyResolver.Current.GetService(typeof(IApplicationConfiguration)); 
     var identity = HttpContext.Current.User.Identity; 
     if (Request.IsAuthenticated) 
     { 
      roles = Roles.GetRolesForUser(identity.Name); 
     } 
     else 
     { 
      roles = new[] { applicationConfiguration.UnknownUserRoleName }; 
     } 
     var webIdentity = new WebIdentity(identity, roles); 
     var principal = new WebsitePrincipal(webIdentity) 
     { 
      ApplicationConfiguration = applicationConfiguration 
     }; 

     HttpContext.Current.User = principal; 
    } 
    . 
    . 
    . 
} 

Risoluzione Mapping

public class ApplicationConfigurationContractMapping : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IApplicationConfiguration>() 
      .To<ApplicationConfiguration>(); 
    } 
} 

ApplicationConfiguration

public class ApplicationConfiguration : IApplicationConfiguration 
{ 
    . 
    . 
    . 
    . 
} 

Sto usando Ninject come framework Injection della dipendenza. Ogni suggerimento è apprezzato.

EDIT: codice completo può essere visto qui: https://github.com/dibley1973/Dibware.Template.Presentation.Web

risposta

9

Non si può evitare di dover chiamare sia il quadro DI o un'astrazione su di esso nella vostra Application_PostAuthenticateRequest, ma che non dovrebbe essere un problema , dal momento che questo Application_PostAuthenticateRequest può essere considerato come parte del tuo Composition Root. O in altre parole: devi risolvere da qualche parte.

Il problema nel tuo caso, tuttavia, è che questo metodo contiene un sacco di codice, e il vero problema è che qui manca un'astrazione. Per risolvere ciò, estrai tutta la logica di questo metodo in una nuova classe e nascondila dietro un'astrazione. Che cosa sarà lasciato è il seguente codice:

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) 
{ 
    var provider = (IPostAuthenticateRequestProvider) 
     DependencyResolver.Current.GetService(typeof(IPostAuthenticateRequestProvider)); 

    provider.ApplyPrincipleToCurrentRequest(); 
} 

Il codice può essere costruito dal contenitore, ed avrà la seguente firma:

public class MvcPostAuthenticateRequestProvider : IPostAuthenticateRequestProvider 
{ 
    private readonly IApplicationConfiguration configuration; 

    public MvcPostAuthenticateRequestProvider(IApplicationConfiguration configuration) 
    { 
     this.configuration = configuration; 
    } 

    public void ApplyPrincipleToCurrentRequest() 
    { 
     // ... 
    } 
} 
+1

Oooh che sembra piuttosto dolce, grazie. Darò quel andare e feedback. – Dib

+1

Che funziona a meraviglia e sembra bello e pulito. Grazie – Dib

1

Seguendo il suggerimento di Steven, il codice finale era:

Una nuova interfaccia "IPostAuthenticateRequestProvider"

/// <summary> 
/// Defines the expected members of a PostAuthenticateRequestProvider 
/// </summary> 
internal interface IPostAuthenticateRequestProvider 
{ 
    /// <summary> 
    /// Applies a correctly setup principle to the Http request 
    /// </summary> 
    /// <param name="httpContext"></param> 
    void ApplyPrincipleToHttpRequest(HttpContext httpContext); 
} 

Una classe tha concreta t implementa "IPostAuthenticateRequestProvider"

/// <summary> 
/// Provides PostAuthenticateRequest functionality 
/// </summary> 
public class MvcPostAuthenticateRequestProvider : IPostAuthenticateRequestProvider 
{ 
    #region Declarations 

    private readonly IApplicationConfiguration _configuration; 

    #endregion 

    #region Constructors 

    public MvcPostAuthenticateRequestProvider(IApplicationConfiguration configuration) 
    { 
     _configuration = configuration; 
    } 

    #endregion 

    #region IPostAuthenticateRequestProvider Members 

    /// <summary> 
    /// Applies a correctly setup principle to the Http request 
    /// </summary> 
    /// <param name="httpContext"></param> 
    public void ApplyPrincipleToHttpRequest(HttpContext httpContext) 
    { 
     // declare a collection to hold roles for the current user 
     String[] roles; 

     // Get the current identity 
     var identity = HttpContext.Current.User.Identity; 

     // Check if the request is authenticated... 
     if (httpContext.Request.IsAuthenticated) 
     { 
      // ...it is so load the roles collection for the user 
      roles = Roles.GetRolesForUser(identity.Name); 
     } 
     else 
     { 
      // ...it isn't so load the collection with the unknown role 
      roles = new[] { _configuration.UnknownUserRoleName }; 
     } 

     // Create a new WebIdenty from the current identity 
     // and using the roles collection just populated 
     var webIdentity = new WebIdentity(identity, roles); 

     // Create a principal using the web identity and load it 
     // with the app configuration 
     var principal = new WebsitePrincipal(webIdentity) 
     { 
      ApplicationConfiguration = _configuration 
     }; 

     // Set the user for the specified Http context 
     httpContext.User = principal; 
    } 

    #endregion 
} 

E in global.asax ...

public class MvcApplication : NinjectHttpApplication 
{ 
    /// <summary> 
    /// Handles the PostAuthenticateRequest event of the Application control. 
    /// </summary> 
    /// <param name="sender">The source of the event.</param> 
    /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> 
    protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) 
    { 
     // Get a PostAuthenticateRequestProvider and use this to apply a 
     // correctly configured principal to the current http request 
     var provider = (IPostAuthenticateRequestProvider) 
      DependencyResolver.Current.GetService(typeof(IPostAuthenticateRequestProvider)); 
     provider.ApplyPrincipleToHttpRequest(HttpContext.Current); 
    } 
. 
. 
}