Adventures on the edge

Learning new development technologies
    "When living on the bleeding edge - you sometimes have to bleed" -BillKrat

ASP.NET MVC4 - Setting up Dependency Injection (Unity) Revised

Back in 2011 I wrote an article after studying Brad Wilson’s article on controllers; I based my UnityControllerFactory on his work; the controller factory is how you hook an IOC container into MVC 4.   It is possible that since 2011 there are newer/improved ways of doing this, but I opted to simply blow the dust off of old code, build a new ASP.NET MVC 4 website from Visual Studio 2012, plug in my old project, and update the article to help a fellow developer in this forum thread.

The following animated gif displays the output of this SOURCE CODE when you click on the refresh button in the browser.   Note that the page will default to the “Foo2” implementation upon startup because of the the following Web.Config setting:

<appSettings>
<add key ="DefaultFoo" value="Foo2"/>
AnimatedMVC4
Figure 1.  Refresh button being hit on Index page.
 

From that point on the AppSettings will be maintained in memory and can be updated as needed - in our case we use the AppSettings “DefaultFoo” setting to determine whether we are going to use Foo1 or Foo2 (they both implement IFoo).

In the source code you’ll find a Gwn.Library.Controller project, it contains the necessary framework components to quickly standup a MVC 4 website using Unity dependency injection - it also contains the mock classes (Foo stuff).   Lines 35 and 36 in the top pane of figure 2 are responsible for swapping out the implementation used by lines 22-30.

To setup a new project to utilize my Dependency Injection hook, it will take four steps:

  1. Create your ASP.NET MVC 4 website
  2. Right click on references and select Manage NuGet packages to install the Microsoft Unity IOC package.
  3. Add a reference to the Gwn.Library.Controller project
  4. Update the Controller and Global.asax classes with the content highlighted in yellow boxes.

That’s pretty much it - everything else is gravy after that.

MVC4Source

Figure 2 source code updates to applicable classes

The ControllerFactoryInitialize() method on line 28 in the bottom pane of figure 2 above is what “hooks” our UnityControllerFactory class into the framework.  

We can use a new RegisterTypes() override, provided by the HttpApplicationBase class, to register our implementation in the Unity container.   By default, registrations are “Transient” which means a new implementation is instantiated each request from the container.   We need AppSettings to be a singleton because it not only pulls in the AppSettings into a collection (which we only want to do once) but also permits us to update that collection programmatically so I use the following parameter:
    new ContainerControlledLifetimeManager()
to let Unity know it will be a singleton - it is not a singleton in the true sense (static class) but within the context that the same instance is always served up when requested.

With my AppSettings being a singleton I can now use the following code:
   AppSettings.SetSettings(DefaultFoo, toggleKey);
on line 36 of figure 2 (top pane) to update the value to a toggled state.

Note above on lines 35 and 36 (bottom pane) that I register two implementations of IFoo - I give them names that match their class names for convenience.  This allows me to to programmatically select the concrete class to use for the IFoo implementation by simply getting the current setting (which will be “Foo1” or “Foo2”). 

Reference the GetDefaultFoo() method below - I invoke the following:
    var configKey = _settings.GetSettings(“DefaultFoo”)
    var returnValue = _provider.Resolve<IFoo>(configKey); 

The first time I call this method the value will come from what was pulled in from the App.Config and subsequent use will come from any updates made to the AppSettings.          

using Gwn.Library.Controller.Interfaces;
using Microsoft.Practices.Unity;

namespace Gwn.Library.Controller.Mocks
{
public class FooFactory
{
private readonly IUnityContainer _provider;
private readonly IAppSettings _settings;

/// <summary>
/// Initializes a new instance of the FooFactory class.
/// Using construction injection to set the implementation
/// for IUnityContainer and IAppSettings
/// </summary>
/// <param name="provider">The provider.</param>
/// <param name="settings">The settings.</param>
public FooFactory(
IUnityContainer provider, IAppSettings settings)
{
_provider = provider;
_settings = settings;
}

/// <summary>
/// Gets the default foo based on Web.Config setting.
/// </summary>
/// <returns>IFoo.</returns>
public IFoo GetDefaultFoo()
{
// Get the "defaultFoo" setting from the Web.Config file
var configKey = _settings.GetSetting("DefaultFoo");

// Use named value to retrieve IFoo
var returnValue = _provider.Resolve<IFoo>(configKey);
return returnValue;
}
}
}

Note in our AppSettings constructor below that I pull the settings from the Web.config file into our _appSettings field.   The SetSettings will add or update collection values as applicable.
using System.Linq;
using System.Web.Configuration;
using Gwn.Library.Controller.Interfaces;
using System.Collections.Specialized;

namespace Gwn.Library.Controller.Implementation
{
public class AppSettings : IAppSettings
{
private readonly NameValueCollection _appSettings;
public AppSettings()
{
_appSettings = WebConfigurationManager.AppSettings;
}

public string GetSetting(string key)
{
return _appSettings.AllKeys.Any(k => k == key)
? _appSettings[key]
: "";
}

public void SetSetting(string key, string value)
{
if (_appSettings.AllKeys.Any(k => k == key))
_appSettings[key] = value; // Update
else
_appSettings.Add(key, value); // Add
}
}
}

Comments are closed