In this article, we will learn about how to read configuration using IOptions Pattern in ASP.NET Core. We normally have many settings in our application that are different for each environment like third-party service URLs, database connection string, email settings, log parameters, etc. We normally set these values in some configuration files so that we are able to change these values without the need to recompile the application.
ASP.NET Core uses appsettings.json file for such settings and this file is read when the application starts. Also, we can configure to read code to read these settings even after startup, i.e. we can change values even when the application is running.
Ins ASP.NET Core there is more than one source to read configuration values from like Environment variables, settings file, command-line arguments, directory files, in-memory objects, etc.
This article will cover how to read configuration using IOptions pattern from appsettings.json file.
Table of Contents
Options Pattern
Option pattern uses classes to bind a group of related configuration settings to a strong typed access i.e. class will have properties that correspond to some setting in the configuration file. These classes are registered in the dependency injection containers to be injected into services, controllers, etc using constructor dependency injection.
Options pattern helps in keeping settings of the different sections separate i.e. setting for logging can be separate from setting for database connectivity.
For details on dependency injection, you can read my other article on Dependency Injection in ASP.NET Core 3.1
Type of options interfaces
There are 3 type of interfaces supported by options pattern
IOptions<TOptions> – Reads configuration data once when the application starts and any changes in configuration will require the application to be restarted. It is registered in the dependency injection container with a singleton lifetime.
IOptionsSnapshot<TOptions> – Reads configuration on every request. Any changes in configuration while the application is running will be available for new requests without the need to restart the application. It is registered in the dependency injection container as a scoped lifetime. Being a scoped service it receives current options values at the time the object is constructed.
IOptionsMonitor<TOptions> – It is a combination of IOptions & IOptionsSnapshot. Supports re-binding configuration but it is only when configuration changes and not on every request like IOptionsSnapshot. It is registered in the dependency injection container as a singleton lifetime (same as IOptions).
Once the options pattern is configured then it can be injected via dependency injection using one of the available interfaces.
Implement IOptions Pattern
Here is a short & quick video on how to read configuration using IOptions pattern in ASP.NET Core
For a demonstration of options pattern to read configuration using IOptions Pattern in ASP.NET Core, we will be creating a Web API project and read configuration file values using options pattern
Create ASP.NET Core Project
To demonstrate read configuration using IOptions pattern in ASP.NET Core we will be creating a project of type API as shown below.
Add Parameters to appsettings.json
Lets add some sample settings in appsettings.json file to be read using IOptions Pattern
{ "ApplicationParameters": { "SQLServerConnection": "SQL Server Connection String", "EmailServer": "127.0.0.1", "ServiceURL": "https://procodeguide.com/getpost", "MaxLimitUsers": 3000 } }
We have added setting section named ApplicationParameters & have added four parameters under it i.e. SQLServerConnection, EmailServer, ServiceURL & MaxLimitUsers
Add properties class
We will add a properties class that corresponds to the settings specified in the appsettings.json ApplicationParameters section.
public class ApplicationParameters { public string SQLServerConnection { get; set; } public string EmailServer { get; set; } public string ServiceURL { get; set; } public long MaxLimitUsers { get; set; } }
Bind configuration to your class in Startup class
Let’s add a service in the startup class to read configuration using IOptions Pattern in ASP.NET Core into an instance of properties class ApplicationParameters.
public class Startup { public Startup(IWebHostEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); Configuration = builder.Build(); } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.Configure<ApplicationParameters>( this.Configuration.GetSection("ApplicationParameters")); } //Remaining code has been removed }
The default order in which values are read from JSON file is
- appsettings.json
- appsettings.{environment}.json
i.e. if same key exists in both appsettings.json & appsettings.{environment}.json then on runtime it should display the value from appsettings.{environment}.json
Add a controller to read parameters using IOptions
The sample controller has been added to inject configuration in constructor injection using IOptions & IOptionsSnapshot interfaces. It has one action index which return values of configuration parameters read using IOptions & IoptionsSnapshot
[Route("api/[controller]")] [ApiController] public class AppParamtersController : ControllerBase { private ApplicationParameters applicationParameters; private ApplicationParameters applicationParametersSnapshot; public AppParamtersController(IOptions<ApplicationParameters> options, IOptionsSnapshot<ApplicationParameters> optionsSnap) { applicationParameters = options.Value; applicationParametersSnapshot = optionsSnap.Value; } [HttpGet] public IActionResult Index() { StringBuilder response = new StringBuilder(); response.AppendLine("IOptions ==>"); response.AppendLine(JsonConvert.SerializeObject(applicationParameters)); response.AppendLine(""); response.AppendLine("IOptionsSnapshot ==>"); response.AppendLine(JsonConvert.SerializeObject(applicationParametersSnapshot)); return Content(response.ToString()); } }
In above controller we have are using IOptions pattern to read configuration values in ASP.NET Core.
Let’s run & test the code to read configuration using IOptions Pattern in ASP.NET Core
When we run the code and navigate to path API/AppParamters/Index then configuration values are displayed for IOption & IOptionsSnapshot. Both values match as it has been read when the app started.
Now without stopping application modify values in appsettings.json to new values & save changes
Now refresh browser (without restarting application) and check values for both IOptions & IOptionsSnapshot. You will see that only IOptionsSnapshot contains the latest modified values as it is designed to read values before each request
IOptionsMonitor also works in a way similar to IOptionsSnapshot only difference being in the IOptionMonitor service lifetime is Singleton instead of Scoped as in IOptionsSnapshot.
Guidelines for storing configuration values
We saw how to read configuration using IOptions Pattern in ASP.NET Core but let’s understand few guidelines on do’s & don’ts that should be followed while storing values in configuration files.
- All sensitive data like passwords, personal information should never be stored in plain text in configuration i.e. if at all it is being stored in configuration then it should be encrypted.
- As far as possible production secrets should be different from development & staging secrets.
- Use different naming conventions for configuration files on different environments like appsettings.development.json and appsettings.production.json.
Summary
We saw how to read configuration using IOptions Pattern in ASP.NET Core. We can inject IOption into service, controller, etc using constructor injection.
There are 3 types of IOptions interface IOptions, IOptionsSnapshot & IOptionsMonitor. IOptionsSnapshot & IOptionsMonitor allows you to read modified parameters even while the application is running.
References: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-3.1
Download Source Code
Here is the source code for demonstration of how to read configuration using IOptions Pattern in ASP.NET Core
https://github.com/procodeguide/Sample.OptionsPattern