Friday, October 28, 2011

Enabling Dependency Injection In Web Forms Pages and User Controls using Spring.NET

In one of the previous post, I mentioned, How MVC3 and Web Forms can exist side by side in one project.  We also saw, how we could Enable Dependency Injection using Spring.NET in an MVC3 Application.

But, What about the old Web Form pages and user controls?  Can we Enable Dependency Injection in them, so that we can create loosely coupled code?

Surely there is a way of doing this using Spring.NET.  In this post we will carry on from where we left and we will try to enable Dependency Injection even for Web Pages and User Controls.  Before moving any further, if you have not already seen my previous post of integrating Spring.NET with MVC3 Application, now is a good time to see it.

Without wasting any more time, let's see how we can enable Dependency Injection in Web Forms and User Controls using Spring.NET

How Do they Do it?

For sake of this post, let's say we have a web page called Default.aspx under the Pages directory.  The structure of the project looks somewhat like this

The project structure with Default.aspx
Our task is to inject the AccountService into the Default.aspx page.  As mentioned in the previous post AccountService is a class that was already configured in Spring.NET, it has one method UserCount and we are going to show the user count on the Default.aspx page.

The steps to enabled dependency injection in web-forms web pages using Spring.NET are as follows:
  • Add HttpHandler, called Spring.Web.Support.PageHandlerFactory for path *.aspx
  • Make code changes to Default.aspx to fetch the UserCount from AccountService
  • Configure the dependencies of Default.aspx in web.xml (web.xml is a spring config file which we created in the previous post)
Let look at each step in more detail.

Step - 1 - Add HttpHandler Spring.Web.Support.PageHandlerFactory for path *.aspx

This step is pretty straight forward all we need to do is, Add an HttpHandler, called Spring.Web.Support.PageHandlerFactory.  We need to configure it against the path *.aspx.  This is required so that, Spring.NET gets an opportunity to perform Dependency Injection when a request comes for any web-forms web page. 

We need to add the handler to the <httpHandlers> tag in the web.config.  Updated web.config looks like

Step - 2 - Make code changes to Default.aspx to fetch the UserCount from AccountService

Lets look at the Default.aspx page
As you can see the html code of Default.aspx is very simple. It just has a label called userCount which will hold the value of number of users in the system.

We will get the value of userCount from AccoutService. Let's look at the code of Default.aspx.cs file The code of Default.aspx.cs has no surprises, it has a property AccoutService. We will plan to injet an implementation of AccoutService using Spring.NET.  In the Page_Load method, we simply set the userCount label with the value returned by the UserCount method of AccoutService.

The only question left to answer is, how do we inject the AccoutService into the Default.aspx.cs. 

Step - 3 - Configure the dependencies of Page Default.aspx in web.xml

For configuring the AccoutService dependency in Default.aspx we have to add the following object declaration in web.xml
Notice that we simply have to add the declaration of Default.aspx with proper path in web.xml. Since, Default.aspx is located in the Pages directory, we have to refer it as ~/Pages/Default.aspx. We have to add all the dependencies for the page, just like how we do it for other Spring.NET objects.

All set, lets test our setup and browser the page Default.aspx to see the result.
Enabled Dependency Injection in web.forms using Spring.NET
As you can see, we are able to see the user count value on the page.  We have successfully Enabled Dependency Injection in Web-Forms Web Pages.

Lets quickly see how we can enable dependency injection in User Controls.  Steps to do that are as follows:
  • Create a user control called UserCount.ascx that invokes AccountService to get the user count
  • Update the Default.aspx to use the UserCount.ascx user control
  • Configure the UserCount.ascx in web.xml
Step - 1 - Create a user control called UserCount.ascx that invokes AccountService to get the user count 

We are going to create a very simple user control.  Let's call it UserCont.ascx.  This user control will simply fetch the user count using the AccountService and show it on the UI.
The code of UserCount.ascx is very simillar to what we have already seen in Default.aspx.  We are setting the value of userCount label by invoking the UserCount() method of AccountService instance.

Notice that, we are not instantiating AccountService anywhere in the user control. We will inject it using Spring.NET.  Before we look at, how exactly we do that lets update the Default.aspx to make use of the UserCount.ascx user control.

Step - 2 - Update the Default.aspx to use the UserCount.ascx user control

Let look at the updated Default.aspx
Nothing very alarming here. We simply are including the user control UserCount.ascx and showing it on the html.

Step - 3 - Configure the UserCount.ascx in web.xml

The final step is to configure the UserCount.ascx in web.xml.  Here is how we do it.
Notice that we registered the UserCount.ascx in Spring.NET configuration file. We simply have to specify the complete path of the UserCount.ascx.  Notice that we didn't have to change the configuration for Default.aspx at all.  Spring.NET is smart enought to inject the correct instance of UserCount.ascx in Default.aspx.

Another important thing to notice is that we have to add abstract="true" to the declaration of UserCount.ascx. 

All set, let's see the setup in action

Enabled Dependency Injection in user controls using Spring.NET
As we can see, we see two lines on the page showing the UserCount, first one is getting the user count directly from Default.aspx web page, while the second line is coming from the UserCount.ascx user control.

Mission Accomplished!
Have some Fun!