How do I NOT use DependencyResolver.Current.GetService(...) in this situation
Following Steven's suggestion, the final code was:
A new interface "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);
}
A concrete class that implements "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
}
And 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);
}
.
.
}
You can't prevent having to call either the DI Container or an abstraction over it in your Application_PostAuthenticateRequest
, but that shouldn't be a problem, since this Application_PostAuthenticateRequest
can be considered to be part of your Composition Root. Or in other words: you have to resolve it somewhere.
The problem in your case, however, is that this method contains an awful lot of code, and the real problem is that you are missing an abstraction. To resolve this, extract all logic of this method into a new class and hide it behind an abstraction. What will be left is the following code:
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
var provider = (IPostAuthenticateRequestProvider)
DependencyResolver.Current.GetService(typeof(IPostAuthenticateRequestProvider));
provider.ApplyPrincipleToCurrentRequest();
}
The code can be built up by your DI Container, and will have the following signature:
public class MvcPostAuthenticateRequestProvider : IPostAuthenticateRequestProvider
{
private readonly IApplicationConfiguration configuration;
public MvcPostAuthenticateRequestProvider(IApplicationConfiguration configuration)
{
this.configuration = configuration;
}
public void ApplyPrincipleToCurrentRequest()
{
// ...
}
}