.net, C# tip, Clean Code, Dependency Injection, Inversion of Control, MVC, Solid Principles

How to use built-in dependency inversion in MVC6 and ASP.NET Core

I’ve previously posted about the new logging features in ASP.NET Core RC1 and MVC6. This time I’m going to write about how Microsoft now has dependency inversion baked into the new Core framework.

Dependency inversion is a well documented and understood principle – it’s what the D stands for in SOLID, and says that your code should only depend on abstractions, not concrete implementations. So plug your services into your application through interfaces.

ojfhi
No

In previous versions of MVC, I’ve needed to download a 3rd party library to assist with dependency inversion – these libraries are also sometimes called “containers”. Examples of containers I’ve used are NInject.MVC, Autofac, and Sprint.NET.

In MVC6, Microsoft has entered this field, by including a simple container in the new version of ASP.NET. This isn’t intended to replicate all the features of other containers – but it provides dependency inversion features which may be suitable for many projects. This allows us to avoid adding a heavyweight 3rd party dependency to our solution (at least until there’s a feature we need from it).

Getting started

For our example, first create the default MVC6 web application in Visual Studio 2015.

webapp1.png

Now let’s create a simple stubbed service and interface to get some users. We’ll save this in the “Services”folder of the project.

public interface IUserService
{
    IEnumerable<User> Get();
}

We’ll need a User object too – we’ll put this in the “Models” folder.

public class User
{
    public string Name { getset; }
}

Let’s create a concrete implementation of this interface, and save this in the “Services” folder too.

public class UserService : IUserService
{
    public IEnumerable<User> Get()
    {
        return new List<User>{ new User { Name = "Jeremy" } };
    }
}

Now modify the HomeController to allow us to display these users on the Index page – we need to change the constructor (to inject the interface as a class dependency), and to change the Index action to actually get the users.

public class HomeController : Controller
{
    private readonly IUserService _userService;
 
    public HomeController(IUserService userService)
    {
        _userService = userService;
    }
 
    public IActionResult Index()
    {
        var users = _userService.Get();
        return View(users);
    }
}

If we just run our project now, we’ll get an exception – the HomeController’s Index action is trying to get users, but the IUserService has not been instantiated yet.

error

We need to configure the services that the container knows about. This is where Microsoft’s new dependency inversion container comes in. You just need to add a single line of code in the ConfigureServices method in Startup.cs to make sure the controller is given a concrete instance of UserService when it asks the container “Can you give me something that implements IUserService?

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddTransient<IUserServiceUserService>();
}

If we run the project again now, we won’t get any exceptions – obviously we’d have to change the Index view to display the users.

Transient, Scoped, Singleton, Instance

In the example above, I used the “AddTransient” method to register the service. There’s actually 4 options to register services:

  • AddTransient
  • AddScoped
  • AddSingleton
  • AddInstance

Which option you choose depends on the lifetime of your service:

  • Transient services are created each time they are called. This would be useful for a light service, or when you need to guarantee that every call to this service comes from a fresh instantiation (like a random number generator).
  • Scoped services are created once per request. Entity Framework contexts are a good example of this kind of service.
  • Singleton services are created once and then every request after that uses the service that was created the first time. A static calculation engine might be a good candidate for this kind of service.
  • Instance services are similar to Singleton services, but they’re created at application startup from the ConfigureServices method (whereas the Singleton service is only created when the first request is made). Instantiating the service at startup would be useful if the service is slow to start up, so this would save the site’s first user from experiencing poor performance.

Conclusion

Microsoft have added their own dependency inversion container to the new ASP.NET Core framework in MVC6. This should be good enough for the needs of many ASP.NET projects, and potentially allows us to avoid adding a heavyweight third party IoC container.

.net, C# tip, Clean Code, MVC, nuget, Solid Principles, WebActivatorEx

MVC Tip – Use WebActivatorEx to clean up your boot-strapping logic

The code snippet below shows the Application_Start method inside Global.asax.cs for a default MVC4 implementation.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
 
    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    AuthConfig.RegisterAuth();
}

In the default implementation, it looks alright – not too messy. But I’ve seen some implementations of this method which are much longer – code to manage NInject registrations, Automapper, and View Engines. So I’ve learned to see this method as somewhere that quickly starts to violate the Single Responsibility Principle.

WebActivatorEx

It’s actually really easy to keep your code clean using WebActivatorEx. This is available as a nuget package that allows a class to be called either just before (or just after) application start-up.

You can install it to your project using the command in the Package Manager Console:

Install-Package WebActivatorEx 

Let’s look at de-coupling Application_Start from the reference to AuthConfig.RegisterAuth(). If we prefix the namespace with a call to WebActivatorEx (as shown below) this method will be called before the Application_Start method.

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MvcApplication1.AuthConfig), "RegisterAuth")]
namespace MvcApplication1
{
    public static class AuthConfig
    {
        public static void RegisterAuth()
        {
            // ...authorization logic here...
        }
    }
}

I love this pattern because it means that the logic for calling the method at start-up is contained within the same method’s class. We don’t need to call it from the Application_Start method, so we’ve cleanly de-coupled two the classes from each other.