|
|
Introduction
In an ASP.NET application, the WebForms framework creates pages and controls using reflection in a way that cannot be intercepted for constructor injection to be performed. Property injection is the best available strategy, and Autofac provides the Autofac.Integration.Web library to achieve flexible property injection for ASP.NET pages and user controls.
Typical Configuration
Referenced Assemblies
For ASP.NET to work with Autofac, both Autofac.dll and Autofac.Integration.Web.dll must be referenced by the application or placed in the /Bin directory.
Web.config
The next step is to add the Autofac HTTP Modules to the Web.config file:
<configuration>
<system.web>
<httpModules>
<add name="ContainerDisposal" type="Autofac.Integration.Web.ContainerDisposalModule, Autofac.Integration.Web"/>
<add name="PropertyInjection" type="Autofac.Integration.Web.PropertyInjectionModule, Autofac.Integration.Web"/>The Container Disposal Module lets Autofac dispose of any components created during request processing as soon as the request completes. The Property Injection Module injects dependencies into pages before the page lifecycle executes. (An alternative Unset Property Injection module is also provided.)
Global.asax
The dependency injection modules expect that the HttpApplication instance supports IContainerProviderAccessor. A complete global application class is shown below:
public class Global : HttpApplication, IContainerProviderAccessor
{
static IContainerProvider _containerProvider;
protected void Application_Start(object sender, EventArgs e)
{
var builder = new ContainerBuilder();
builder.Register<SomeDependency>().FactoryScoped();
_containerProvider = new ContainerProvider(builder.Build());
}
public IContainerProvider ContainerProvider
{
get { return _containerProvider; }
}
}IContainerProvider exposes two useful properties: ApplicationContainer and RequestContainer. The first is the root container that was built at application start-up. The second, RequestContainer should be used whenever manual dependency resolution/service lookup is required. The components that it contains (apart from any singletons) will be specific to the current request.
Implementing Pages and User Controls
Pages and UserControls that require dependencies should expose their dependencies as public properties:
// MyPage.aspx.cs
public partial class MyPage : Page
{
public IFoo SomeDependency { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
// SomeDependency will be set by Autofac.
// In a production application the property accessor would check for null.
label1.Text = SomeDependency.SomeMessage;
}
}Explicit Configuration
When adding dependency injection to an existing application, it is usually necessary to distinguish between pages that will have their dependencies injected, and those that will not. The InjectPropertiesAttribute attribute in Autofac.Integration.Web, coupled with the AttributedInjectionModule help to achieve this.
First, replace the PropertyInjection HTTP Handler with the AttributedInjection handler:
<add name="AttributedInjection" type="Autofac.Integration.Web.AttributedInjectionModule, Autofac.Integration.Web"/>
Once this is in place, pages and controls will not have their dependencies injected by default. Instead, they must be marked:
[InjectProperties]
public partial class MyPage : Page
{
// ...Integrating by Hand (Base Page and Control Classes)
Most applications that would benefit from a base Page or Control class (those with non-injectable existing pages) should use the AttributedInjectionModule described above.
If it is desired, however, dependency injection can be done in the Page_PreInit() handler in a base page class:
protected void Page_PreInit(object sender, EventArgs e)
{
var cpa = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
var cp = cpa.ContainerProvider;
cp.RequestContainer.InjectProperties(this);
}This approach is also worth considering if you have an application with a vast number of pages and only wish to apply dependency injection to a few of them.
Customising Dependency Injection Models
If the provided Property, Unset Property, and Attributed dependency injection models are unsuitable, it is very easy to create a customised injection behaviour. Simply subclass Autofac.Integration.Web.DependencyInjectionModule and use the result in Web.config.
There is one abstract member to implement:
protected abstract IInjectionBehaviour GetInjectionBehaviourForHandlerType(Type handlerType);
The returned IInjectionBehaviour can be one of the predefined NoInjection, PropertyInjection or UnsetPropertyInjection properties, or a custom implementation of the IInjectionBehaviour interface.
Status
The ASP.NET integration is available in the Autofac download archives.
Credits
Building this module was made much easier by this great article over at Geoff Lane's blog.
Sign in to add a comment
