ASP.NET Web Forms Integration Guide
ASP.NET Web Forms was never designed with dependency injection in mind. Although using constructor injection in our
Page classes, user controls and http handlers would be preferable, it is unfortunately not possible, because ASP.NET expects those types to have a default constructor.
Note: This blog post shows how to do constructor injection in pages and user controls, but please keep in mind that this will fail when trying to run the application in partial trust. Besides, it still doesn't work for IHttpHandlers.
Instead of doing constructor injection, there are alternatives. The simplest thing to do is to request instances directly from the container inside the constructor of your
Page classes.
using SimpleInjector;
public class Global : System.Web.HttpApplication
{
private static Container container;
[System.Diagnostics.DebuggerStepThrough]
public static TService GetInstance<TService>()
where TService : class
{
return container.GetInstance<TService>();
}
protected void Application_Start(object sender,
EventArgs e)
{
Bootstrap();
}
private static void Bootstrap()
{
// 1. Create a new Simple Injector container
var container = new Container();
// 2. Configure the container (register)
container.Register<IUserRepository, SqlUserRepository>();
container.Register<IUserContext, AspNetUserContext>();
// 3. Optionally verify the container's configuration.
container.Verify();
VerifyPages(container);
// 4. Store the container for use by Page classes.
Global.container = container;
}
// This method tests if each Page class can be created.
// Because Page classes manually call GetInstance<T> in
// their ctor, we want to test on application startup
// if all dependencies can be resolved, to prevent
// having to go through each page in the application
// during testing.
private static void VerifyPages(Container container)
{
var assemblies =
BuildManager.GetReferencedAssemblies()
.Cast<Assembly>();
var pageTypes =
from assembly in assemblies
from type in assembly.GetExportedTypes()
where typeof(Page).IsAssignableFrom(type)
where !type.IsAbstract
select type;
foreach (Type pageType in pageTypes)
{
container.GetInstance(pageType);
}
}
}
With this code in place, we can now write our page classes, user controls, and http handlers as follows:
public partial class _Default : System.Web.UI.Page
{
private readonly IUserRepository userRepository;
private readonly IUserContext userContext;
public _Default()
{
this.userRepository =
Global.GetInstance<IUserRepository>();
this.userContext =
Global.GetInstance<IUserContext>();
}
protected void Page_Load(object sender, EventArgs e)
{
if (this.UserContext.IsAdministrator)
{
this.UserRepository.DoSomeStuff();
}
}
}