Share via


ASP.NET Dependency Injection HTTP Module

You can use an HTTP module, an extension to the ASP.NET HttpApplicationState class, and code in Global.asax to force ASP.NET to automatically inject dependent objects at every page request, as discussed in the topic ASP.NET Web Forms Applications.

The following code shows a suitable HTTP module that captures the PreRequestHandlerExecute event to insert itself into the ASP.NET execution pipeline. On each page request, the handler resolves the current HTTP handler through the container using the BuildUp method and then captures the OnPageInitComplete event. When the OnPageInitComplete executes, the module code walks the complete control tree, resolving each control through the container using the BuildUp method.

The BuildUp method takes an existing object instance, resolves and populates any dependencies specified for the class, and then returns the instance. If there are no dependencies, it simply returns the original instance.

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using Microsoft.Practices.Unity;

namespace Unity.Web
{
  public class UnityHttpModule : IHttpModule
  {
    public void Init(HttpApplication context)
    {
      context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
    }

    public void Dispose() { }

    private void OnPreRequestHandlerExecute(object sender, EventArgs e)
    {
      IHttpHandler currentHandler = HttpContext.Current.Handler;
      HttpContext.Current.Application.GetContainer().BuildUp(
                          currentHandler.GetType(), currentHandler);

      // User Controls are ready to be built up after page initialization is complete
      var currentPage = HttpContext.Current.Handler as Page;
      if (currentPage != null)
      {
        currentPage.InitComplete += OnPageInitComplete;
      }
    }

    // Build up each control in the page's control tree
    private void OnPageInitComplete(object sender, EventArgs e)
    {
      var currentPage = (Page)sender;
      IUnityContainer container = HttpContext.Current.Application.GetContainer();
      foreach (Control c in GetControlTree(currentPage))
      {
        container.BuildUp(c.GetType(), c);
      }
      context.PreRequestHandlerExecute -= OnPreRequestHandlerExecute;
    }

    // Get the controls in the page's control tree excluding the page itself
    private IEnumerable<Control> GetControlTree(Control root)
    {
      foreach (Control child in root.Controls)
      {
        yield return child;
        foreach (Control c in GetControlTree(child))
        {
          yield return c;
        }
      }
    }
  }
}
'Usage
Imports System
Imports System.Collections.Generic
Imports System.Web
Imports System.Web.UI
Imports Microsoft.Practices.Unity 
Namespace Unity.Web

  Public Class UnityHttpModule
    Implements IHttpModule

    Public Sub Init(ByVal context As HttpApplication) _
               Implements System.Web.IHttpModule.Init
      AddHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute
    End Sub

    Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
    End Sub

    Private Sub OnPreRequestHandlerExecute(ByVal sender As Object, ByVal e As EventArgs)
      Dim currentHandler As IHttpHandler = HttpContext.Current.Handler
      HttpContext.Current.Application.GetContainer().BuildUp( _
                          currentHandler.[GetType](), currentHandler)

      ' User Controls are ready to be built up after page initialization is complete
      Dim currentPage = TryCast(HttpContext.Current.Handler, Page)
      If Not currentPage Is Nothing Then
        AddHandler currentPage.InitComplete, AddressOf OnPageInitComplete
      End If
    End Sub

    ' Build up each control in the page's control tree
    Private Sub OnPageInitComplete(ByVal sender As Object, ByVal e As EventArgs)
      Dim currentPage = DirectCast(sender, Page)
      Dim container As IUnityContainer = _ HttpContext.Current.Application.GetContainer()
      For Each c As Control In GetControlTree(currentPage)
        container.BuildUp(c.[GetType](), c)
      Next
      RemoveHandler context.PreRequestHandlerExecute, AddressOf OnPreRequestHandlerExecute
    End Sub

    ' Get the controls in the page's control tree excluding the page itself
    Private Function GetControlTree(ByVal root As Control) As IEnumerable(Of Control)
      Dim controlList As New List(Of Control)
      For Each child As Control In root.Controls
        If child Is Nothing Then
          Exit For
        Else
          controlList.Add(child)
        End If
        For Each c As Control In GetControlTree(child)
          If child Is Nothing Then
            Exit For
          Else
            controlList.Add(child)
          End If
        Next
      Next
      Return controlList
    End Function

  End Class

End Namespace