Using ASP.NET Core goodies in a console app

The problem

I've been working a lot on ASP.net Core web applications recently and have really come to enjoy the built in dependency injection and configuration libraries.

I was recently building a console app using .NET Core and really missed having these goodies available to me. There are .NET standard libraries, so there was no reason I couldn't use them, but I hit a few snags on the way. For ASP.net, Visual Studio does a great job of adding everything for you as well as wiring everything up. The documentation is also pretty much all ASP.net focused. Hopefully this article will help someone else trying to add these goodies to their apps. If not, I have a record for myself :)

I'm not going to go into all the details of how these various libraries work, just some high-level tips and how to use them outside ASP.net core. You should be able to follow the Microsoft docs for the details.

1. Configuration

.NET framework apps manage configuration in an XML file called app.config / web.config (in the <appsettings/> section). There are static helper classes available that one could use to then access the values.

This functionality is no longer available, instead ASP.net Core introduced a variety of options for managing configuration. The one I'm most familiar with is a JSON file, but there are many others, see here

Other cool features include:

  • Automatically binding your settings to C# objects, taking types into account. This is a huge improvement over the <appsettings> method where everything comes back as a string.
  • The concept of hierarchical / cascading settings. A developer can define a base settings file and then override specific properties based on some logic, e.g. the environment that the app is executing in.

To get this configuration into your application:

  1. Install the required Nuget packages:
    1. Microsoft.Extensions.Configuration
    2. Microsoft.Extensions.Configuration.FileExtensions
    3. Microsoft.Extensions.Configuration.Binder
    4. Microsoft.Extensions.Configuration.Json
  2. Add an appsettings.json file to your project root, and make sure its set to copy to the output folder on build.

    {
         "ConnectionStrings" : {
             "Connection": "localhost,..."
         }
         "configKey" : "someValue",
         "configSection" : {
             "key": 123
         }
    }
    
  3. Add the following in your Program.cs file, in Main()

    var config = new ConfigurationBuilder()
                 .AddJsonFile("appsettings.json", false, true)
                 .Build();
    
  4. You can then access your setting wherever you need them with

    config["configKey"]; //Dictionary syntax
    //or
    config.GetSection("configSection")["key"]; 
    //or
    config.GetConnectionString("Connection"); //Syntactical sugar over config.GetSection["ConnectionString"]
    
  5. To bind the config to a matching object:

    class ConfigSection() 
    {
        public int key { get; set; }
    } 
    
    
    /**********************************/
    var myConfig = new ConfigSection();
    var config = config.GetSection("configSection");
    config.Bind(myConfig);
    
  6. We can set it up to auto-bind but for that we'll need dependency injection, so lets look at that.

Dependency Injection

There are many 3rd party dependency injection frameworks that you may have used before, but ASP.net core comes with a built in one that is pretty simple, but really effective for most use cases.

  1. Install the required Nuget packages:
    1. Microsoft.Extensions.DependencyInjection
    2. Microsoft.Extension.Options.ConfigurationExtensions
  2. Add the following in your Program.cs file, in Main()

                var serviceCollection = new ServiceCollection()
                    // If you're using Entity Framework, configure the Context
                    .AddDbContext<MyDbContext>(builder => builder                                   
                          .UseSqlServer(config.GetConnectionString("Connection"))
                    )
                    // If you need access to the raw config, do this here
                    .AddSingleton<IConfiguration>(config)
                    // Register any other dependencies
                    .AddSingleton<IService, Service>()                        
                    .AddSingleton<IService2, Service2>()
                    .AddSingleton<IService3, Service3>()
                    .AddSingleton<IService4, Service4>()
                    // Register your config bindings
                    .Configure<ConfigSection>(config.GetSection("configSection"));
                    .BuildServiceProvider();
    
  3. Now, because ASP.net is not the entry point, you will have to look up the first service, but the DI will ensure all of the following dependencies are resolved and injected.

    serviceCollection.GetService<IService>().DoSomething();
    
  4. For more on the ASP.net DI tooling, check the docs

But wait, there's more

ASP.net core has many more useful libraries that could probably be used in console apps, I haven't needed any yet, but I'll definitely have a look at them in the future and figure out what is required to get them working on their own.

Things like: