Build Your Own Application Framework: The Power of an Inversion of Control Container

matt-honeycutt-v1Welcome to Part 2 of this review of the Pluralsight course Build Your Own Application Framework with ASP.NET MVC 5 by Matt Honeycutt.

Matt is a software architect specializing in ASP.NET MVC web applications. He has over a decade of experience creating web applications. As an avid practitioner of Test-Driven Development, he has created both the SpecsFor and SpecsFor.Mvc frameworks.

Matt has served as the lead developer on numerous multi-million dollar software projects and enjoys finding elegant solutions to difficult problems.

On Github, he has published the Heroic Framework and the Fail Tracker web app. These projects feature much of the code and techniques that are covered in this course.

Also in this series:

Part 1 -What is an Application Framework?
Part 2 – The Power of an Inversion of Control Container
Part 3 – Optimize Your Controller Layer
Part 4 – Optimize Your View Layer
Part 5 – Optimize Your JavaScript

In this module we create the heart of our application framework with Structure Map.

Matt gives a rapid overview of what Inversion of Control is all about. If you are new to the concept of Inversion of Control, or want to review a number of different available IoC containers, Matt recommends John Sonmez’s course Inversion of Control and generally agree with this advice.

I should also say that John Sonmez produced a more recently course Practical IoC with ASP.NET MVC4. While that course is mostly focused on Unity, the final module of John’s course covers other IoC Containers including StructureMap.

As well as some knowledge of Inversion of Control, it is important to have some understanding of LINQ and Tasks in .NET.

The Power of an Inversion of Control Container

Structure Map Basics

This course covers version 2.6.4.1 of Structure Map. At the time of writing Structure Map has reached v4.x, and while the changes from v3 to v4 were relatively small, the changes from v2.x to v3 were huge.

If you decide to use Structure Map as your application framework’s IoC container, you will probably want to use the latest version. So to get the most out of this module of the course, pay attention to the design patterns and principles that can be applied to any version of Structure Map, and indeed any IoC container.

Also bare in mind that Jon Sonmez’s Inversion of Control course is based on an old version of Structure Map and that significant improvements have been made in the more recent versions.

Matt describes the main elements of Structure Map:

  • IContainer, with methods Configuration, Instance Creation and Lifecycle Management
  • ObjectFactory, with methods Container and Service Locator
  • Registry, with methods Configuration and Scanning
  • Nested Container, with Scoped Container, Handles IDisposable and Controlled Lifecycle

Matt warns that Service Location can be a dangerous design pattern to utilize.

The above Wikipedia link lists several disadvantages, including that fact that the registry makes the code more difficult to maintain (opposed to using Dependency injection), because it becomes unclear when you would be introducing a breaking change.

For these reasons, this course only makes very sparing use of ObjectFactory. Version 4 of Structure Map has actually removed ObjectFactory altogether.

Responding to some criticism for removing the ObjectFactory, Jeremy Miller, the StructureMap lead developer, has said:

“…it’s easy to roll your own if you still want the static container. All it was anyway was a static facade over Container anyway. Some of the worst experiences with user support of SM have been related to naive developers shooting themselves in the foot w/ ObjectFactory.”

If you are wondering how to implement this framework without the ObjectFactory, see Heroic.Web.IoC which has been updated to work with StructureMap v4

Demo: Adding StructureMap

This demo achieves the following tasks:

  • Add StructureMap Package
  • Implement Dependency Resolver
  • Register Standard Conventions
  • Controller Injection

Matt creates an ASP.NET MVC 5 application in Visual Studio and adds some new folders:

  • Data (for Entity Framework specific code – e.g. ApplicationDbContext.cs)
  • Domain (for our domain entities – e.g. ApplicationUser.cs)
  • Infrastructure (most of what we create in this module will go here)

Out of the box, MVC only supports parameters with parameterless constructors.
This give the yellow screen of death: No parameterless constructor defined for this object.

We can fix this by hooking in an IoC Container.

Matt shows how to install Structure Map with Nuget:

PM> Install-Package StructureMap

Next we create StructureMapDependencyResolver.cs, which implements System.Web.Mvc.IDependencyResolver

For now, we use ObjectFactory, which is StructureMap’s Static Container.

Please bare in mind that this is now obsolete.

We also see how to tell MVC to use StructureMap in Global.asax.cs:


protected void Application_Start()
{
...
DependencyResolver.SetResolver(new StructureMapDependencyResolver());
}

When we build and rerun our app, we no longer get the yellow screen of death.

Now, what happens if we have a dependency on an interface?

We find out by creating a dummy ISayHello interface and implementing type in our HomeController.cs.

 

We see the yellow screen of death again:

StructureMap Exception Code: 202 No Default Instance defined for…ISayHello”

It doesn’t know which concrete type to use to satisfy that dependency.

Because we haven’t yet configured StructureMap itself. We can set this up in our Global.asax file:

ObjectFactory.Configure(cfg =>
{
//Scan all the types in our web application project and apply the Default Conventions
//i.e. ISomeType=>SomeType

cfg.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
});
}

Demo: Implementing the Container-Per-Request Pattern

Structure Map is now almost integrated into our application. We can build on this with the Container Per Request Pattern.

Having a Container-Per-Request implicitly gives us a unique session, or in our case an Entity Framework Context Per Request.

Matt demonstrates that our constructor is being call once as one context is created, and then again as a second context is created. And our dispose method never gets called.

So two contexts are being created to serve a single web request, one for each of our controllers.

This is something we can fix with Nested Containers and the Container Per Request Pattern.

 

A nested container differs from a normal container in two key ways:

1. Transient objects are singleton. i.e. creates only one ApplicationDbContext.
2. Disposes objects recursively, all objects within it are disposed with the container

We begin in Global.asax.cs and add a wrapper property to simplify storing and retrieving our Nested Container.

Next we store the items collection of the current HttpContext, which is already tied to the currently executing web request.

We also hook into the Application_BeginRequest and Application_EndRequest.events.

If you haven’t come across these life cycle events before, you can read Joydip Kanjilal’s Understanding the Global.asax file, or even better, see Alex Wolf’s course The MVC Request Life Cycle. If you want to learn MVC in depth, I highly recommend studying Alex Wolf’s course as well as this one.

 

There are some times when you don’t want an instance to be reused, even within the scope of a Nested Container.

If, in our view, we add a second Render Action call to our controllers widget action:

<p>@Html.Action(“IssueWidget”, “Issue”)</p>
<p>@Html.Action(“IssueWidget”, “Issue”)</p>

This gives another Yellow Screen Of Death:

A single instance of controller … cannot be used to handle multiple requests

This is because MVC doesn’t allow a single instance of a controller to be reused, even for Child requests, such as those created by Render Action.

We need our container to create a new instance of a controller each time we request one.

Matt creates a ControllerConvention class:


public class ControllerConvention : IRegistrationConvention
{
public class ControllerConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (type.CanBeCastTo(typeof(Controller)) && !type.IsAbstract)
{
registry.For(type).LifecycleIs(new UniquePerRequestLifecycle());
//This lifecycle causes StructureMap to create a new instance of our controllers
//even when one if requested from a Nested Container
}
}
}
}

Once this is hooked in, Structure Map calls our Process method for each type that it finds.

To hook this convention in, we update global.asax.cs. Inside our call to ObjectFactory.Configure, we add the line

scan.With(new ControllerConvention());

For further information see the official Structure Map documentation on Nested Containers, and Jeremy Miller: “Nested Containers” in StructureMap 2.6.1

Demo: Injecting Into Action Filters – Part 1

Matt warns that doing Dependency Injection into Action Filters isn’t straightforward as we might think.

We use StructureMap’s setter injection capabilities instead of constructor injection.

However we first see where we are with our application. We can now create, view and delete issues.

Next, we want to find out which users are making which changes in the system. We will do this by logging activities to our database:

Matt shows us a new LogAction class, which is associated to our Entity Framework Context and allows us to add Log entries to track who is doing what.

We see new logging code added to each IssueController action method, with almost identical code in each method.

We see in SQL Server that the logging works as we hoped, however this approach to logging adds a lot of noise to our code, making it harder to spot the real logic in our action methods.

A better way to handle this cross-cutting operation is to use a LogAction Filter

MVC let’s us create a Log Action Filter that we can use instead.

namespace FailTracker.Web.Filters
{
public class LogAttribute : ActionFilterAttribute
{
//property for our context
public ApplicationDbContext Context { get; set; }

public string Description { get; set; }
public LogAttribute(string description)
{
Description = description;
}
}

//perform our logging after our action is executed
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//var context = new ApplicationDbContext(); //problem. ideally this would be injected

//see property declared above
var user = Context.Users.Find(userId);

}
}

This logic is similar to the login logic that was previously embedded in our Action methods, but it frees us from writing repetitive code.

There is one problem though; it creates it’s own DbContext.

We’d like to declare out dependency in our constructor, but unfortunately we cannot do constructor injection into attributes (e.g. Action Filters).

Attributes can only be initialized with compile-time constant expressions.

So instead, Matt demonstrates setter injection. This involves declaring our dependencies as public properties.

Demo: Injecting Into Action Filters – Part 2

Matt begins this lesson by adding a StructureMapFilterProvider, which inherits from Microsoft’s FilterAttributeFilterProvider class.

In this class, we override GetFilters, using the base implementation and then our container. We use Structure Map to build up the Action Filter objects.

Next we just need to wire everything up in our container. This is done in global.asax.cs and again inside the call to ObjectFactory.Configure.

Structure Map v2.x will not perform Setter Injection into properties by default. We have to tell it which properties to inject into.

We define a convention, and Matt walks through a lambda expression written inside our call to ObjectFactory.Configure.

With this done, we can now add the Log attribute above each of our action methods in our Issue Controller using data annotations. The functionality that this gives us means that we can now remove all of the noisy code from those methods.

We see that although the logging broadly works, we have lost the ability to log the id of the issue that was viewed or deleted.

To regain this, we can add support for referencing Action parameters within our Log descriptions. Matt shows us how we easily do this by simply updating our annotations.

By the end of this lesson, we have a fully working generic logging solution in place.

Demo: Cleaning Up With Registries

Our IoC configuration code is becoming complex. So let’s refactor our configuration:

Registries are a StructureMap concept that allows us to modularize our configuration into separate classes.

We first create a StandardRegistry class, inheriting from StuctureMap’s Registry class. We also create a ControllerRegistry which also inherits from Registry.

Each of these new registries scan the calling assembly.

This is the same code as we previous wrote in our Global.asax.cs – so we can now replace that old code with two lines of code which add each new registry.

We also see the creation of an ActionFilterRegistry.cs using the same pattern. This allows us to further simplify our Global.asax.cs, and we now simply have three calls to AddRegistry there.

Registering Common Abstractions

Our application framework is now capable of creating our Controller, our Action Filters, and the services they need to handle a request from our users.

In this lesson, Matt demonstrates how to configure StructureMap to inject common ASP.NET abstractions such as:

  • The current HttpContext
  • Our application’s route data
  • Our own abstractions e.g. for the Current User

The demo begins with the creation of a new MvcRegistry class:

public class MvcRegistry : Registry
{
public MvcRegistry()
{
For<BundleCollection>().Use(BundleTable.Bundles);
For<RouteCollection>().Use(RouteTable.Routes);
For<IIdentity>().Use(() => HttpContext.Current.User.Identity);
For<HttpSessionStateBase>()
.Use(() => new HttpSessionStateWrapper(HttpContext.Current.Session));
For<HttpContextBase>()
.Use(() => new HttpContextWrapper(HttpContext.Current));
For<HttpServerUtilityBase>()
.Use(() => new HttpServerUtilityWrapper(HttpContext.Current.Server))
}
}

Global.asax:
cfg.AddRegistry(new MvcRegistry());

Matt explains that our application is already tightly coupled to the ASP.NET Identity system, and that it will become increasingly difficult to switch out this technology if we don’t address this code smell now:

We can create an abstraction for accessing the current user:

public class CurrentUser : ICurrentUser
{

public ApplicationUser User
{
//abstract so that we can easily switch our identity model
get { return _user ?? (_user = _context.Users.Find(_identity.GetUserId()))); }
}
}

Demo: Creating a Flexible Task System

We create the infrastructure we need to Register and Execute Tasks, and then use it to automatically load SeedData into an empty Database.

Our tasks will implement the Transaction Per Request pattern:

In this demo we see that we need several new interfaces:

IRunAfterEachRequest.cs
IRunAtInit.cs – for tasks called at application initialization
IRunAtStartup.cs – for tasks called at application startup, after initialization
IRunOnEachRequest.cs – for tasks that are executed at the beginning of each web request
IRunOnError.cs – allows a task to be notified whenever an unhandled exception occurs in our application

We also create a Task Registry and scan for the assemblies that start with “FailTracker” (ignoring Microsoft and other 3rd party assemblies) and add types of all of our new interfaces.

In our constructor:

public TaskRegistry()
{
Scan(scan =>
{
scan.AssembliesFromApplicationBaseDirectory(a => a.FullName.StartsWith(“FailTracker”));
scan.AddAllTypesOf<IRunAtInit>();

});
}

Version 4 of StructureMap has introduced Type Scanning Diagnostics. The documentation shows that we can use container.WhatDidIScan to list out all conventions and scanned assemblies.

Again, we hook in our registries in Global.asax.cs, so we add this to our lambda expression argument for ObjectFactory.Configure.

To actually utilize these tasks. Each runs inside the scope of a Nested Container:

using (var container = ObjectFactory.Container.GetNestedContainer())
{
foreach (var task in container.GetAllInstances<IRunAtInit>())
{
task.Execute();
}

foreach (var task in container.GetAllInstances<IRunAtStartup>())
{
task.Execute();
}
}

Matt also adds a foreach loops into our Application_BeginRequest and Application_EndRequest lifecycle methods.

For Application_EndRequest Matt puts the foreach inside the try block and puts the container disposal code in a finally block.

The last thing we see in this lesson is the foreach IRunOnError instance code added into our new Application_Error method.

We now have an architecture that supports tasks. So next we create something to utilize it.

Demo: Loading Seed Data With a Task

We can load to data to facilitate local testing and development.

We create a new SeedData class which is executed only once during application startup.

We will only add test users if there are no existing users in our database, and we must save our changes to persist them.

public class SeedData : IRunAtStartup
{

public void Execute()
{
if (!_context.Users.Any())
{
_context.Users.Add(new ApplicationUser
{
UserName = “TestUser”
});

_context.SaveChanges();
}

if (!_context.Issues.Any())
{

}
}
}

Demo: Implementing the Transaction-Per-Request Pattern With Tasks

Our requests are not truly atomic. This means there is a risk that our requests will throw an error, but part of the request changes will still be persisted.

We see an example of this, with Matt throwing an InvalidOperationException after we save our changes to the database.

We can fix this with the Transaction Per Request Pattern, which is another name for the Unit of Work pattern.

If you’ve never heard of the Unit of Work pattern before, it may be worth taking 20 minutes out of this course study to watch Scott Allen’s explanation and demonstration in the Design Patterns Library course. The basic idea is very simple however:

At the beginning of each request, we are going to start a new transaction.

We will only commit the transaction if an error has not occurred at the end of the request.

If we have an error before the end of the request, we rollback the transaction.

It is also important to have some understanding of Transaction Isolation Levels.

public class TransactionPerRequest : IRunOnEachRequest, IRunOnError, IRunOnEachRequest
{
… //ctor

void IRunOnEachRequest.Execute()
{
_httpContext.Items[“_Transaction”] = _dbContext.Database.BeginTransaction(…)
}

void IRunOnError.Execute()
{…}

void IRunAfterEachRequest.Execute()
{…}
}

Once the code is in place, Matt shows that this successfully prevents data for being written when there is an error.

We also see that the data is written successfully when no error occurs.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s