I have seen this common pattern to get connection strings, application configuration settings and logger in ASP.NET core application;
public class HomeController
{
private IUnitOfWork _unitOfWork;
private IConfiguration _configuration;
private AppConfig _appConfiguration;
private readonly ILogger _logger;
public HomeController(IUnitOfWork unitOfWork, IConfiguration configuration, IOptions<AppConfig> appConfiguration, ILogger<ProjectController> logger)
{
_unitOfWork = unitOfWork;
_configuration = configuration;
_appConfiguration = appConfiguration.Value;
_logger = logger;
}
This works fine but it’s reparative for configurations and logger and violates DRY principal. A good alternative is this;
Register these assemblies in your startup (startup.cs) to take advantage of dependency feature;
public void ConfigureServices(IServiceCollection services)
{
//Add functionality to inject IOptions<T>
services.AddOptions();
//Add our Config object so it can be injected
services.Configure<ConnectionString>(Configuration.GetSection("ConnectionStrings"));
services.Configure<AppConfig>(Configuration.GetSection("AppConfig"));
}
UPDATE @10/18/2022
For .NET 6, the configuration is;
builder.Services.AddOptions();
builder.Services.Configure<ConnectionString>(builder.Configuration.GetSection("ConnectionStrings"));
builder.Services.Configure<AppConfig>(builder.Configuration.GetSection("AppConfig"));
Create AppConfig POCO class;
public class AppConfig
{
public string ApplicationName { get; set; }
public string Version { get; set; }
}
Create a base class and declare these services as properties.
using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using ConfigDemo.Models;
public abstract class BaseController<T> : Controller where T : BaseController<T>
{
private ILogger<T> _logger;
private IConfiguration _configuration;
private IOptions<ConnectionString> _appConnectionString;
private IOptions<AppConfig> _appConfiguration;
protected ILogger<T> Logger => _logger ?? (_logger = HttpContext?.RequestServices.GetService<ILogger<T>>());
protected IConfiguration Configuration => _configuration ?? (_configuration = HttpContext?.RequestServices.GetService<IConfiguration>());
protected IOptions<ConnectionString> AppConnectionString => _appConnectionString ?? (_appConnectionString = (HttpContext?.RequestServices.GetService<IOptions<ConnectionString>>()));
protected IOptions<AppConfig> AppConfiguration => _appConfiguration ?? (_appConfiguration = (HttpContext?.RequestServices.GetService<IOptions<AppConfig>>()));
protected string DisplayMessage
{
get { return TempData["DisplayMessage"] == null ? String.Empty : TempData["DisplayMessage"].ToString(); }
set { TempData["DisplayMessage"] = value; }
}
}
We have these values in our appsettings.json file that we would like to use in our application;
{
"ConnectionStrings": {
"DBConnection1": "Data Source=(local);Initial Catalog=MyDb1;Persist Security Info=True;Integrated Security=True",
"DBConnection2": "Data Source=(local);Initial Catalog=MyDb2;Persist Security Info=True;Integrated Security=True"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
//application configratuion here
"AppConfig": {
"ApplicationName": "MyApp",
"Version": "1.0.0"
}
}
Let’s create a demo view to display output values;
@model String
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Result</title>
</head>
<body>
<div>
@Model
</div>
</body>
</html>
Finally create our first HomeController by inheriting from base controller to read config values;
public class HomeController : BaseController<HomeController>
{
//Navigate to URL, for example https://localhost:44320/home/simpleconfig
public string Index()
{
Logger.LogInformation("I am using dependency injection created in the base cotroller");
return "Navigate to URL to show an example";
}
//using configuration
public ViewResult SimpleConfig()
{
var configValue = Configuration.GetSection("AppConfig").GetChildren();
string result = configValue.Select(i => i.Value).Aggregate((i, j) => i + "," + j );
// generate the view
return View("Result",
(object)String.Format("Simple Config value: {0}", result));
}
//using strong type
public ViewResult ConfigValueFromConfig()
{
string configValue = AppConfiguration.Value.ApplicationName;
// generate the view
return View("Result",
(object)String.Format("App Config value: {0}", configValue));
}
Run your application and navigate to action method like this;
You can download sample project from GitHub;
https://github.com/shahzy1/ConfigDemoApplication/tree/main
Resources
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0