structuremap

Getting Started with Dependency Injection in ASP.NET Core

I've lately been feeling my way around getting an actual, production-ready ASP.NET Core app developed, and one of the features I've really been digging (one of many) is native support for Dependency Injection (DI). DI is huge in modern web apps, so making it the default for ASP.NET Core applications is, IMO, a big step forward for this framework.

But, at the moment, the documentation page for dependency injection in ASP.NET Core has an example that just didn't click with me, and I believe that's because they didn't have any code examples to provide. In this post, I will provide two examples: one of my own design, and one which recreates an example provided in the official documentation; both of these sample projects are now over on GitHub. Let's learn how to use Dependency Injection in ASP.NET Core!

What Is Dependency Injection?

First, a few basics. The idea of Dependency Injection is that, when a class is created, it should have its dependent classes injected into it rather than created by it. This provides a situation in which we have loose coupling and high cohesion, an ideal which many software programs strive toward.

The ASP.NET Core documents explains it like this:

"[When using DI, ]Rather than directly instantiating collaborators, or using static references, the objects a class needs in order to perform its actions are provided to the class in some fashion. Most often, classes will declare their dependencies via their constructor, allowing them to follow the Explicit Dependencies Principle. This approach is known as 'constructor injection'."

Constructor injection is by far the most common approach to implementing DI, though not the only one. ASP.NET Core uses constructor injection in its solution, so (obviously) we will also do so.

Finally, note that there are many DI frameworks out there in addition to the native ASP.NET Core one, including StructureMap, Autofac, Ninject, SimpleInjector, and several others. StructureMap is my personal favorite, but all of these frameworks do roughly the same thing. Try a few to figure out which fits your style; in this demo I will use the native ASP.NET Core DI container.

A Basic DI Example

To demonstrate how Dependency Injection works in an ASP.NET Core app, let's set up a basic MVC app as a demo.

Pretend we need to model a list of users for our application. The class which represents these users might look like this:

public class User  
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Username { get; set; }
}

We will also need an interface and repository for retrieving the users. The interface and class will look like this:

public interface IUserRepository  
{
    List<User> GetAll();
}

public class UserRepository : IUserRepository  
{
    public List<User> GetAll()
    {
        return new List<User>()
        {
            new User()
            {
                FirstName = "Ash",
                LastName = "Ketchum",
                DateOfBirth = new DateTime(1997, 12, 30),
                Username = "ichooseyou"
            },
            new User()
            {
                FirstName = "Brock",
                LastName = "Harrison",
                DateOfBirth = new DateTime(1992, 3,31),
                Username = "rockrulez"
            },
            new User()
            {
                FirstName = "Misty",
                LastName = "",
                DateOfBirth = new DateTime(1999, 5,4),
                Username = "ihearttogepi"
            }
        };
    }
}

The reason we need an interface here is because our MVC controllers will reference the interface, not the class. Speaking of the controller, let's define one now:

public class HomeController : Controller  
{
    private readonly IUserRepository _userRepo;

    public HomeController(IUserRepository userRepo)
    {
        _userRepo = userRepo;
    }

    [HttpGet]
    public IActionResult Index()
    {
        return View(_userRepo.GetAll());
    }
}

Notice the setup here. We have a private readonly instance of our interface IUserRepository, and the constructor takes an instance of IUserRepository and sets our private instance to the passed-in instance. This is constructor injection at its simplest.

But we're not done yet. As I've discussed previously on this blog, ASP.NET Core projects have a Startup.cs file, which configures the environment in which our app will run. The Startup.cs file also places services into ASP.NET Core's Services layer, which is what enables dependency injection.

Here's how we must modify our Startup.cs file to inject IUserRepository into our controller:

public void ConfigureServices(IServiceCollection services)  
{
    // Add framework services.
    services.AddMvc();

    //Basic demo
    services.AddTransient<IUserRepository, UserRepository>();
}

We'll discuss what AddTransient<>() means in the next section. For now, let's run the app.

Here's what our page looks like when we get there:

Note that once we added the IUserRepository to the Services layer, ASP.NET Core automatically injected it into our HomeController class. That's pretty neat!

But, what exactly does AddTransient<>() do in the Startup file? To discuss that, we must first discuss what ASP.NET Core uses as lifetimes for its services.

Dependency Injection Lifetimes

In ASP.NET Core's DI implementation, we see the concept of "lifetimes". A lifetime specifies when a DI-injected object gets created or recreated. There are three possibilities:

  • Transient: Created each time they are requested.
  • Scoped: Created once per request.
  • Singleton: Created the first time they are requested. Each subsequent request uses the instance that was created the first time.

The ASP.NET Core official documentation provides a walkthrough of sorts for how these lifetimes behave, but I'm not satisfied with that example as it skips over a few sections of code that I think are rather important and doesn't provide a working example. I've reproduced it here, with a full working codebase which, like the earlier example, is over on GitHub.

To demonstrate how these lifetimes work, let's define a few interfaces. We'll need an interface IOperation which represents an operation being done in each of these lifetimes. Said operation will do one thing: it will return either Guid.NewGuid() or the passed-in Guid value from its one method. We'll also define four additional interfaces, each of which represents that operation during a specific lifetime:

public interface IOperation  
{
    Guid GetCurrentID();
}

public interface IOperationTransient : IOperation { }

public interface IOperationScoped : IOperation { }

public interface IOperationSingleton : IOperation { }

public interface IOperationSingletonInstance : IOperation { }  

IOperationSingletonInstance is a special form of this operation which will always return a blank Guid.

Now we can define the Operation class itself, which implements the four lifetime interfaces and defines the GetCurrentID() method.

public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance  
{
    public Guid Guid { get; set; }

    public Operation()
    {
        Guid = Guid.NewGuid();
    }

    public Operation(Guid guid)
    {
        Guid = guid;
    }

    public Guid GetCurrentID()
    {
        return Guid;
    }
}

Our Operation class will either return Guid.NewGuid() or used the Guid passed in to the constructor (this scenario is for the IOperationSingletonInstance interface demo).

However, to fully show how Transient operations work, we also need to define another class which represents a separate set of instances of these interfaces (separate from the ones being injected into our controller). We'll call this class OperationServices and it looks like this:

public class OperationService  
{
    public IOperationTransient TransientOperation { get; }
    public IOperationScoped ScopedOperation { get; }
    public IOperationSingleton SingletonOperation { get; }
    public IOperationSingletonInstance SingletonInstanceOperation { get; }

    public OperationService(IOperationTransient transientOperation,
        IOperationScoped scopedOperation,
        IOperationSingleton singletonOperation,
        IOperationSingletonInstance instanceOperation)
    {
        TransientOperation = transientOperation;
        ScopedOperation = scopedOperation;
        SingletonOperation = singletonOperation;
        SingletonInstanceOperation = instanceOperation;
    }
}

Now we need to register the four lifetime interfaces and our OperationServices class into our Dependency Injection container. We do so in the Startup class's ConfigureServices() method, just like we registered the IUserRepository class earlier.

public void ConfigureServices(IServiceCollection services)  
{
    // Add framework services.
    services.AddMvc();

    //Basic demo
    services.AddTransient<IUserRepository, UserRepository>();

    //Lifetimes demo
    services.AddTransient<IOperationTransient, Operation>();
    services.AddScoped<IOperationScoped, Operation>();
    services.AddSingleton<IOperationSingleton, Operation>();
    services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
    services.AddTransient<OperationService, OperationService>();
}

With all our dependencies registered, we can now create an OperationsController which will demo how these lifetimes work.

public class OperationsController : Controller  
{
    private readonly OperationService _operationService;
    private readonly IOperationTransient _transientOperation;
    private readonly IOperationScoped _scopedOperation;
    private readonly IOperationSingleton _singletonOperation;
    private readonly IOperationSingletonInstance _singletonInstanceOperation;

    public OperationsController(OperationService operationService,
        IOperationTransient transientOperation,
        IOperationScoped scopedOperation,
        IOperationSingleton singletonOperation,
        IOperationSingletonInstance singletonInstanceOperation)
    {
        _operationService = operationService;
        _transientOperation = transientOperation;
        _scopedOperation = scopedOperation;
        _singletonOperation = singletonOperation;
        _singletonInstanceOperation = singletonInstanceOperation;
    }

    public IActionResult Index()
    {
        // viewbag contains controller-requested services
        ViewBag.Transient = _transientOperation;
        ViewBag.Scoped = _scopedOperation;
        ViewBag.Singleton = _singletonOperation;
        ViewBag.SingletonInstance = _singletonInstanceOperation;

        // operation service has its own requested services
        ViewBag.Service = _operationService;
        return View();
    }
}

For posterity, I will also include the .cshtml file which displays the results of that Index() action:

@{
    ViewData["Title"] = "ASP.NET Core Dependency Injection Demo";
}

<h2>Lifetimes</h2>

<span>Controller Operations</span>  
<ul>  
    <li><strong>Transient:</strong> @ViewBag.Transient.GetCurrentID()</li>
    <li><strong>Scoped:</strong> @ViewBag.Scoped.GetCurrentID()</li>
    <li><strong>Singleton:</strong> @ViewBag.Singleton.GetCurrentID()</li>
    <li><strong>Singleton Instance:</strong> @ViewBag.SingletonInstance.GetCurrentID()</li>
</ul>  
<span>OperationService Operations</span>  
<ul>  
    <li><strong>Transient:</strong> @ViewBag.Service.TransientOperation.GetCurrentID()</li>
    <li><strong>Scoped:</strong> @ViewBag.Service.ScopedOperation.GetCurrentID()</li>
    <li><strong>Singleton:</strong> @ViewBag.Service.SingletonOperation.GetCurrentID()</li>
    <li><strong>Singleton Instance:</strong> @ViewBag.Service.SingletonInstanceOperation.GetCurrentID()</li>
</ul>  

Testing the Lifetimes

With all of our code in place, we are now ready to test. Let's look at two screenshots of that demo page. The first screenshot is when we first load the page.

The second screenshot is of the same page after doing a refresh:

We need to notice a few things about the differences in these screenshots:

  • Each time it shows up, the Transient Guid is different.
  • The Scoped Guids are the same for both calls in a single screenshot, but not in each screenshot.
  • The Singleton Guids are the same all four times they are called.
  • The Singleton Instance Guids (as expected) are always 0s.

I personally find that the differences are easier to spot if I see them in real-time, so I made this gif:

A short demo showing the differences between Transient, Scoped, and Singleton services in ASP.NET Core

Summary

One of the best new features coming from ASP.NET Core is the inclusion of its own lightweight Dependency Injection container. In this post, we've seen how to inject a simple service into a controller, and we've seen the three DI lifetimes (Transient, Scoped, Singleton) and how they behave differently from one another.

As always, please feel free to check out the code base for this post over on GitHub and let me know if you see any improvements I could make.

Happy Coding!

Using AutoMapper with StructureMap in ASP.NET Web API

I'm on a "Combine These Two NuGet Packages in Web API" kick lately, so let's keep that going! We're going to set up an ASP.NET Web API project that uses AutoMapper and StructureMap to provide us with mapping and injection-based repositories and controllers. I already covered how to get started with StructureMap in Setting Up Dependency Injection in ASP.NET Web API, so this post will focus more on what AutoMapper does and how to use it in Dependency Injection (DI) scenarios. Let's get started!

What is AutoMapper?

AutoMapper is a convention-based mapping library that maps values from one instance of an object to another. In most cases, the values will be mapped if the name and type of the properties match in both the source and destination objects. AutoMapper is also very flexible, allowing for you to design an entirely custom mapping rule set to support any scenario. In this post, we'll mostly use AutoMapper's default settings. For more information about one of my favorite NuGet packages ever, read the docs.

Models

First off, we need the models that will be mapped. In this post, I'm assuming that one of the models represents the database structure of the object, and another model represents the Data Transfer Object variation. Here's our models:

public class DbUser  
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int AccessLevelID { get; set; }
    public string Username { get; set; }
}

public class User  
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public AccessLevel AccessLevel { get; set; }
    public string Username { get; set; }
}

public enum AccessLevel  
{
    User,
    Admin,
    Configuration,
    Test
}

Our Repositories will need to map objects of type DbUser to objects of type User. Let's see how that would look.

Repositories

Let's make an IUserRepository interface that we can then use via dependency injection:

public interface IUserRepository  
{
    List<User> GetAll();
}

We now need to implement that interface, but the Repository will need to be able to map the two user objects. In order for that to happen, we need to be able to inject the IMapper interface into the repository, Here's our UserRepository class:

public class UserRepository : IUserRepository  
{
    private IMapper _mapper;

    public UserRepository(IMapper mapper)
    {
        _mapper = mapper;
    }

    public List<User> GetAll()
    {
        List<DbUser> dbUsers = new List<DbUser>()
        {
            new DbUser()
            {
                ID = 1,
                Username = "Anorak",
                FirstName = "James",
                LastName = "Halliday",
                AccessLevelID = 2
            },
            new DbUser()
            {
                ID = 2,
                Username = "Great and Powerful Og",
                FirstName = "Ogden",
                LastName = "Morrow",
                AccessLevelID = 2
            },
            new DbUser()
            {
                ID = 1020994,
                Username = "Parzival",
                FirstName = "Wade",
                LastName = "Watts",
                AccessLevelID = 1
            }
        };

        return _mapper.Map<List<User>>(dbUsers);
    }
}

But wait, don't we need to create a map for AutoMapper so that it knows how to map these objects? We do, but first, we need to set up StructureMap and add some plumbing.

Setting Up StructureMap

In order to set up StructureMap for use in a WebAPI application, I'm using the StructureMap.WebApi2 NuGet package. Said package adds several files to my project:

Screenshot of my sample project, showing the new DependencyResolution folder and new StructuremapMvc and StructuremapWebApi files.

It turns out that I don't need all of these files to implement my solution. So let's remove StructuremapMvc.cs, StructuremapWebApi.cs and StructureMapScopeModule.cs. The resulting file structure looks like this:

Screenshot of my sample project, with the above files removed.

Now we need to do some plumbing to get this structure working. In the App_Start/WebApiConfig.cs file, we need to modify the Register method like so:

public static void Register(HttpConfiguration config)  
{
    // Web API configuration and services

    // Web API routes
    config.MapHttpAttributeRoutes();

    IContainer container = IoC.Initialize();
    GlobalConfiguration.Configuration.DependencyResolver = new StructureMapWebApiDependencyResolver(container);
}

In this method, we create a Dependency Injection container (IContainer) and add it to the global configuration so that it can be used. But where do we tell the container what interfaces and classes to use? In the DefaultRegistry.cs file.

In StructureMap, a Registry is a class that initializes what classes can be injected via the Container. The DefaultRegistry initially looks like this:

public class DefaultRegistry : Registry {  
    #region Constructors and Destructors

    public DefaultRegistry() {
        Scan(
            scan => {
                scan.TheCallingAssembly();
                scan.WithDefaultConventions();
            });
        //For<IExample>().Use<Example>();
    }

    #endregion
}

However, I don't want that Scan() method. What it's supposed to do is automatically find injectable classes and add them to the Container, but I haven't found that it works all that well. Instead, I'll remove it for now, and we'll come back to it after we have set up AutoMapper.

Setting Up AutoMapper

Now let's go get the AutoMapper package. That package doesn't add any new files, so we need to add them ourselves.

AutoMapper works by defining "maps" that map properties from one object type to another. It does this by inspecting each type and assuming that properties which match their type and name will be mapped from one type to the other. Problem is, it doesn't create any of these maps automatically; we have to create them via the use of Profiles.

Let's create a Profile class for AutoMapper and initialize a map that maps DbUser to User:

public class UserProfile : Profile  
{
    protected override void Configure()
    {
        CreateMap<DbUser, User>().ForMember(dest => dest.AccessLevel, opt => opt.MapFrom(src => (AccessLevel)src.AccessLevelID));
    }
}

Note that we had to explicitly define what property DbUser.AccessLevelID mapped to. This is because the properties do not match type, so in this case the map is a simple conversion to an enum.

Once we've got the profile defined, we need StructureMap to include it in the DI container. We can do this many ways, but the way I've found to be the most helpful involves editing the DefaultRegistry.cs file from earlier like so:

public class DefaultRegistry : Registry {  
    public DefaultRegistry() {
        //Get all Profiles
        var profiles = from t in typeof(DefaultRegistry).Assembly.GetTypes()
                        where typeof(Profile).IsAssignableFrom(t)
                        select (Profile)Activator.CreateInstance(t);

        //For each Profile, include that profile in the MapperConfiguration
        var config = new MapperConfiguration(cfg =>
        {
            foreach (var profile in profiles)
            {
                cfg.AddProfile(profile);
            }
        });

        //Create a mapper that will be used by the DI container
        var mapper = config.CreateMapper();

        //Register the DI interfaces with their implementation
        For<IMapperConfiguration>().Use(config);
        For<IMapper>().Use(mapper);
    }
}

We still have an issue we need to solve, though. Remember the UserRepository from earlier? That class expects to receive an IMapper through its constructor. We need to tell the DI container that any time a class requires an object of type IUserRepository, we need to give them a class of type UserRepository. In the DefaultRegistry, we can do that like this:

public class DefaultRegistry : Registry {  
    public DefaultRegistry() {
        ...
        //Register the DI interfaces with their implementation
        For<IMapperConfiguration>().Use(config);
        For<IMapper>().Use(mapper);

        //Register the UserRepository and pass instance of Mapper to its constructor
        For<IUserRepository>().Use<UserRepository>()
            .Ctor<IMapper>().Is(mapper);
    }
}

Phew! That's a lot of plumbing we needed to do! But it'll all be worth it, since creating a controller is now stupid easy.

Creating a DI-Enabled Controller

Let's create a UserController class that will serve requests. We need to pass an instance of UserRepository in the controller's constructor, and we need an action that returns all users.

[RoutePrefix("users")]
public class UserController : ApiController  
{
    private IUserRepository _userRepo;

    public UserController(IUserRepository userRepo)
    {
        _userRepo = userRepo;
    }

    [Route("all")]
    [HttpGet]
    public IHttpActionResult GetAll()
    {
        return Ok(_userRepo.GetAll());
    }
}

Earlier, we needed to explicitly include the repositories into the DI container. We do not do the same for the controllers, since we already implicitly took care of that in the plumbing. All that's left to do now is test the controller.

Testing the Controller

Let's test the controller using Postman. The URL we need to hit is localhost:/users/all. What's our response?

A screenshot of a Postman response, showing status code 200 OK and the correct data returned

Which is exactly what we expected. The system is now fully DI-enabled, and AutoMapper is correctly producing the maps and delivering them to the repositories, where the actual mapping occurs.

Summary

This structure allows us to use AutoMapper and StructureMap in concert, creating extendable, testable, reusable projects at the expense of a lot of plumbing work up front. The steps we followed to enable AutoMapper and StructureMap were:

  1. Create the Models
  2. Create the Repositories
  3. Add StructureMap.WebApi2 NuGet package.
  4. Remove unnecessary StructureMap files.
  5. Add the DI Container to the WebAPI configuration.
  6. Register the Repositories with StructureMap.
  7. Add AutoMapper and Profiles.
  8. Inject IMapper into Repositories.

If you liked this post, check out the sample project, and let me know in the comments!

Happy Coding!

Setting Up Dependency Injection in Web API with StructureMap

Up until recently I hadn't really used any Dependency Injection (DI) frameworks in my ASP.NET projects, largely due to them being rather intimidating to set up the first time. I mean, I barely grasp the concept of DI, so the thought of trying to implement it on my own is worrisome.

Recently, though, my group had a requirement that forced us to consider using a DI framework (which I wrote about in Custom Validation in ASP.NET Web API using FluentValidation) for an ASP.NET Web API project we're in the process of building. We needed a way to pass dependencies to multiple consumers, particularly Web API controller classes and back-end repositories. Further, we needed the solution to be testable, and to be relatively easy to change when necessary.

I started researching different DI setups, and eventually stumbled across one called StructureMap, which after just an hour of exploring, seemed to provide everything our solution needed. The worry I had foreseen was reduced to mere trepidation, and just a little more research showed the kind of power that Dependency Injection really holds.

Of course, if it helps us, it will help someone else out there; hence this post. Let's explore getting started with Dependency Injection in ASP.NET Web API, using StructureMap!

Creating the Project

Let's start at the very beginning (a very good place to start).

Let's create a new Web API project in Visual Studio. I called mine StructureMapWebAPIDemo.

A screenshot of the Visual Studio New Project window.

A screenshot of the Visual Studio New Web Project window, with Web API and No Authentication selected

We'll end up with a project that looks a lot like this:

A screenshot of the initial layout of the Web API project

Setting Up the Library and Repositories

Before we do anything else, let's set up our library project. Add a new Class Library to the solution (I called mine StructureMapWebAPIDemo.Lib) with folders called Interfaces, Repositories, and DataModel. The structure will look like this:

A screenshot of the StructureMapWebAPIDemo.Lib project layout, including folders for DataModel, Repositories, and Interfaces

We'll need a data model class to interface with, so let's create a class called Movie.

public class Movie  
{
    public int ID { get; set; }
    public string Title { get; set; }
    public DateTime ReleaseDate { get; set; }
    public int RunningTimeMinutes { get; set; }
    public string Director { get; set; }
}

We'll also need a Repository and an Interface to retrieve the movies. Here's those classes.

public interface IMovieRepository  
{
    List<Movie> GetAllMovies();
    Movie GetByID(int id);
}

public class MovieRepository : IMovieRepository  
{
    public List<Movie> GetAllMovies()
    {
        return new List<Movie>()
        {
            new Movie()
            {
                ID = 1,
                Title = "The Incredibles",
                ReleaseDate = new DateTime(2004, 11, 5),
                RunningTimeMinutes = 116,
                Director = "Brad Bird"
            },
            new Movie()
            {
                ID = 2,
                Title = "Wreck-It Ralph",
                ReleaseDate = new DateTime(2012, 11, 2),
                RunningTimeMinutes = 120,
                Director = "Rich Moore"
            },
            new Movie()
            {
                ID = 3,
                Title = "Inside Out",
                ReleaseDate = new DateTime(2015, 6, 19),
                RunningTimeMinutes = 102,
                Director = "Pete Doctor & Ronnie Del Carmen"
            }
        };
    }

    public Movie GetByID(int id)
    {
        var allMovies = GetAllMovies();
        if (allMovies.Where(x => x.ID == id).Any())
        {
            return allMovies.First(x => x.ID == id);
        }
        else return null;
    }
}

All the repository does is return either a collection of movies, or an individual movie (or null if given a movie ID that doesn't exist).

Now that we've got our library set up, we can integrate StructureMap.

Adding StructureMap

In the Web API project, let's add a NuGet package called StructureMap.WebApi2. On doing so, we'll see that the structure of the project has changed:

The new files are what allow StructureMap to operate in our Web API project, and if you'd like more information about them, check out the GitHub documentation. Luckily for us, we don't strictly need to know what these files do in order to use them (though understanding what you are building is always a good idea).

Modifying the Controllers

We have one controller in this project at the moment, HomeController. Let's remove this controller and replace it with our own MovieController and two actions which use the MovieRepository from earlier:

[RoutePrefix("movies")]
public class MovieController : ApiController  
{
    [HttpGet]
    [Route("all")]
    public IHttpActionResult All()
    {
        MovieRepository movieRepo = new MovieRepository();
        var allMovies = movieRepo.GetAllMovies();
        return Ok(allMovies);
    }

    [HttpGet]
    [Route("{id}")]
    public IHttpActionResult GetByID(int id)
    {
        MovieRepository movieRepo = new MovieRepository();
        var movie = movieRepo.GetByID(id);
        if(movie == null)
        {
            return NotFound();
        }
        return Ok(movie);
    }
}

On first glance, this all seems fine and dandy. After all, the All() and GetByID() are pretty descriptive insofar as what they do. The issue arises when the implementation of the MovieRepository needs to change.

Let's say (for the sake of argument) that we need to be flexible about what implementation we want for the MovieRepository. Maybe we need to support different data storage systems, maybe we need the possibility of changing the actual code for different scenarios, what have you. The problem we have right now is that new is glue; that is, creating a dependency using the new keyword binds the dependency to the current implementation, whatever that happens to be. If the implementation of the MovieRepository changes, it's likely the code in the MovieController will also need to change.

But what if it didn't have to?

That's the core philosophy behind using a DI container: separate the implementation from the interface. In this way, if the implementation changes, the classes which need that implementation don't actually care, because the interface to the implementation didn't (necessarily) change.

Here's what we need: we need the MovieController to be aware of an interface to the implementation, not the implementation itself. We can do this by creating a private variable in the MovieController class for the repository's interface and assigning the implementation of that interface in the constructor:

[RoutePrefix("movies")]
public class MovieController : ApiController  
{
    private readonly IMovieRepository _movieRepo;

    public MovieController(IMovieRepository movieRepo)
    {
        _movieRepo = movieRepo;
    }

    [HttpGet]
    [Route("all")]
    public IHttpActionResult All()
    {
        var allMovies = _movieRepo.GetAllMovies();
        return Ok(allMovies);
    }

    [HttpGet]
    [Route("{id}")]
    public IHttpActionResult GetByID(int id)
    {
        var movie = _movieRepo.GetByID(id);
        if(movie == null)
        {
            return NotFound();
        }
        return Ok(movie);
    }
}

Now we've got our controller set up perfectly. All we need now are two more steps.

In the DependencyResolution folder's DefaultRegistry.cs file, we need to register the MovieRepository with the DI container:

public class DefaultRegistry : Registry {  
    public DefaultRegistry() {
        Scan(
            scan => {
                scan.TheCallingAssembly();
                scan.WithDefaultConventions();
            });
        For<IMovieRepository>().Use<MovieRepository>();
    }
}

Finally, in the App_Start/WebApiConfig.cs file, we need to start up the DI container:

public static class WebApiConfig  
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        StructuremapWebApi.Start();

        ....
    }
}

This is how we tell StructureMap to inject an instance of MovieRepository into MovieController's constructor for the interface IMovieRepository.

Testing the Controllers

One of the primary benefits of switching to a DI container such as StructureMap is the improved ability to test our code. Unit testing the MovieRepository doesn't change, but unit testing the MovieController does, due to the constructor injection we're performing on it.

Let's set up a stub test class for testing the MovieController:

[TestClass]
public class MoviesControllerTests  
{
    [TestMethod]
    public void Test_GetByID_ValidID()
    {
        //Arrange

        //Act

        //Assert
    }

    [TestMethod]
    public void Test_GetByID_InvalidID()
    {
        //Arrange

        //Act

        //Assert
    }
}

We're going to test two scenarios: when we call the controller's GetByID action with a valid ID, and with an invalid ID.

Valid Movie ID test

Let's write the valid ID test first. The general order of operations for any test is arrange, act, assert.

Arrange

First, we need to arrange the components being tested, as well as their dependencies. Remember that the point of this test is to test the controller, not the repository, and so we'll be mocking the MovieRepository using Moq:

//Arrange
var movieID = 2;  
var mockMovieRepo = new Mock<IMovieRepository>();  
mockMovieRepo.Setup(x => x.GetByID(movieID)).Returns(new Movie() { ID = 2 });  
var controller = new MoviesController(mockMovieRepo.Object);  

Act

Now, we need to perform the action we are testing. Remember that since we are testing a controller, we will get back an IHttpActionResult response, and need to convert that to an appropriate response class (in our case, OkNegotiatedContentResult). Here's the next part of the method:

//Act
IHttpActionResult response = controller.GetByID(movieID);  
var contentResult = response as OkNegotiatedContentResult<Movie>;  

Assert

Finally, we need to assert that three things are true:

  1. The response itself is not null.
  2. The content of the response is not null.
  3. The movie ID we submitted to the controller is the same as the ID of the movie returned.

That code looks like this:

//Assert
Assert.IsNotNull(contentResult);  
Assert.IsNotNull(contentResult.Content);  
Assert.AreEqual(movieID, contentResult.Content.ID);  

The complete test method looks like this:

[TestMethod]
public void Test_GetByID_ValidID()  
{
    //Arrange
    var mockMovieRepo = new Mock<IMovieRepository>();
    var movieID = 2;
    mockMovieRepo.Setup(x => x.GetByID(movieID)).Returns(new Movie() { ID = 2 });
    var controller = new MoviesController(mockMovieRepo.Object);

    //Act
    IHttpActionResult response = controller.GetByID(movieID);
    var contentResult = response as OkNegotiatedContentResult<Movie>;

    //Assert
    Assert.IsNotNull(contentResult);
    Assert.IsNotNull(contentResult.Content);
    Assert.AreEqual(movieID, contentResult.Content.ID);
}

Invalid Movie ID Test

Now we can complete the other test, where we're testing for the result for an invalid ID. In this scenario, the response should be 404 Not Found.

[TestMethod]
public void Test_GetByID_InvalidID()  
{
    //Arrange
    var mockMovieRepo = new Mock<IMovieRepository>();
    var movieID = 6; //This movie does not exist
    mockMovieRepo.Setup(x => x.GetByID(movieID)).Returns((Movie)null);
    var controller = new MoviesController(mockMovieRepo.Object);

    //Act
    IHttpActionResult response = controller.GetByID(movieID);
    var contentResult = response as NotFoundResult;

    //Assert
    Assert.IsNotNull(contentResult);
}

Summary

Dependency Injection's primary purpose is to separate the implementation from the interface, and allow the system to supply the implementation at a given time. StructureMap (and it's Web API implementation) provide most of the groundwork to do just that, and all we programmers have to do is:

  • Register the dependencies
  • Set up the controllers to use injection
  • Test

And then we can sick back and sip our margaritas. Or get back to work. Whichever.

I've got a sample project for this post over on GitHub, so go check it out!

Happy Coding!