ASP.NET vNext: Configuration and Dependency Injection

In my last article I introduced you to the “perfect” configuration handler code. Well, it wasn’t perfect. But it did load all the configuration elements into a container object that you could use anywhere. However, static variables for this are bad. There is no control on what or when to use a specific setting and no knowledge on who needs what configuration. Let’s remove the static identifier and see how we can make the configuration available to other classes – such as your controllers – via dependency injection.

Let’s first of all recap and show off the code within Startup.cs that loads the configuration.

    public class Startup
    {
        public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
        {
            var configBuilder = new ConfigurationBuilder(appEnv.ApplicationBasePath);

            configBuilder.AddJsonFile("config.json", optional: true);
            configBuilder.AddJsonFile($"config-{env.EnvironmentName}.json", optional: true);
            configBuilder.AddEnvironmentVariables();

            Configuration = configBuilder.Build();
        }

        public IConfiguration Configuration
        {
            get;
            private set;
        }

In this new version I’ve removed the word “static”. Yep – a one-word change. However, with the new version, the configuration is no longer generally available (unless you happen to have a reference to the Startup object – something most Controllers don’t have). Let’s also create a DbSettings.cs class to hold our configuration:

namespace TemplateStarterApp.Settings
{
    public class DbSettings
    {
        public string ConnectionString
        {
            get;
            set;
        }
    }
}

Here is the appropriate section in my config-Development.json file:

{
  "Database": {
    "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=test-db;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

At this point, I can use this.Configuration.Get("Database:ConnectionString") to get the value of that connection string. To make it available via DI, I have to create a class to hold it. This is in my Settings folder as a file DbSettings.cs:

namespace TemplateStarterApp.Settings
{
    public class DbSettings
    {
        public string ConnectionString
        {
            get;
            set;
        }
    }
}

Configuring Dependency Injection

A single line in my ConfigureServices() method sets up this model for Dependency Injection:

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<DbSettings>(this.Configuration.GetConfigurationSection("Database"));

            // Rest of the configuration goes here
        }

Note the rename of the GetSubKey() method – it’s now GetConfigurationSection() (as of beta5).

Using Dependency Injection

I want to make the DbSettings available within my HomeController. I do this in the constructor:

using Microsoft.AspNet.Mvc;
using Microsoft.Framework.OptionsModel;
using TemplateStarterApp.Settings;

namespace TemplateStarterApp.Controllers
{
    public class HomeController : Controller
    {
        private DbSettings dbSettings = null;

        public HomeController(IOptions<DbSettings> dbSettings)
        {
            this.dbSettings = dbSettings.Options;
        }

        // GET: //
        public IActionResult Index()
        {
            return View();
        }
    }
}

The dependency injection part of the equation handles creating the HomeController with the appropriate DI class that I’ve set up in the Startup.cs ConfigureServices() method. Once I’ve got the database settings, I just save off those settings for later use.

Where can I use Dependency Injection

Above, I’ve used dependency injection in a controller. However, you can pretty much use this DI technique in any part of an ASP.NET application. A common place to use DI is to get the database settings into the Entity Framework class that creates the database, for example. You could use it in any middleware (for example, your own Authentication middleware). I’m currently writing a Json Web Token parser middleware to provide authentication from a third party system – the configuration of the Json Web Token parser will be handled via DI.

This is an awesome feature of ASP.NET and I hope this tutorial assists in your usage of it.

2 thoughts

    • Thanks – my code got the same cut-and-paste issue your comment got – the DbSettings got removed because it looked like a tag. Should be corrected now.

      Like

Comments are closed.