10

Nach dem Rat, den ich in diesem Thread gegeben habe [Ninject UOW pattern, new ConnectionString after user is authenticated] verstehe ich jetzt, dass ich nicht die folgende Zeile verwenden sollte ...Wie benutze ich NICHT DependencyResolver.Current.GetService (...) in dieser Situation/

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

... als Service Locator ist ein Anti-Pattern.

Aber im Fall des folgenden Verfahrens, wie kann ich mein konkretes Objekt instanziiert, die „IApplicationConfiguration“, so dass ich das Objekt verwenden kann implementiert die unbekannten Benutzerrollennamen zu bekommen, oder es verwenden, um die "zuweisen ApplicationConfiguration "Eigenschaft meines Prinzips?

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

Resolution Mapping-Code

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

ApplicationConfiguration

public class ApplicationConfiguration : IApplicationConfiguration 
{ 
    . 
    . 
    . 
    . 
} 

Ich benutze Ninject als mein Dependency Injection Framework. Irgendwelche Vorschläge geschätzt.

EDIT: Voll Code hier zu sehen ist: https://github.com/dibley1973/Dibware.Template.Presentation.Web

Antwort

9

Sie weder den DI Rahmen oder eine Abstraktion über sie in Ihrem Application_PostAuthenticateRequest, aber das sollte kein Problem sein nennen verhindern kann, die , da diese Application_PostAuthenticateRequest als Teil Ihrer Composition Root angesehen werden kann. Oder mit anderen Worten: Sie müssen sich irgendwo auflösen.

Das Problem in Ihrem Fall ist jedoch, dass diese Methode eine Menge Code enthält, und das eigentliche Problem ist, dass Sie eine Abstraktion hier vermissen. Um dies zu lösen, extrahiere die gesamte Logik dieser Methode in eine neue Klasse und verstecke sie hinter einer Abstraktion. Was bleibt übrig ist der folgende Code:

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

    provider.ApplyPrincipleToCurrentRequest(); 
} 

Der Code kann vom Behälter aufgebaut werden, und die folgende Signatur haben:

public class MvcPostAuthenticateRequestProvider : IPostAuthenticateRequestProvider 
{ 
    private readonly IApplicationConfiguration configuration; 

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

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

Oooh, die ziemlich süß aussieht, danke. Ich werde das geben und Feedback geben. – Dib

+1

Das funktioniert ein Leckerbissen und sieht nett und ordentlich aus. Vielen Dank – Dib

1

Nach Steven Vorschlag war der endgültige Code:

Eine neue Schnittstelle "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); 
} 

Eine konkrete Klasse tha t implementiert "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 
} 

Und 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); 
    } 
. 
. 
} 
Verwandte Themen