In thelast post, we talked about ASP.NET Core Configuration in general.
We saw how is it set up by default from ASP.NET Core.
We also talked about sources and that order matters.
This time we will talk about mapping configuration to classes.
We will also talk about various ways of injecting configuration settings to our application code.
Another useful thing is automatic reload of configuration. We will see how we can have our configuration reloaded while our application is running.
You can find the code with exampleshere.
Let’s say we have following object in ourappsettings.json file:
"Messages": { "ShouldShowAlert": true, "AlertMessage": "This is conditional message.", "RegularMessage": "This is regular message." }
And that we want to get those values and map them to an object.
We would first create a class that matches that structure (or matches only those keys we want to bind):
public class MessagesOptions{ public string AlertMessage { get; set; } public string RegularMessage { get; set; } public bool ShouldShowAlert { get; set; }}
Now I can bind that object from JSON (section) to an instance ofMessageOptions class.
public void ConfigureServices(IServiceCollection services){ services.AddMvc(); var messages = new MessagesOptions(); Configuration.GetSection("Messages").Bind(messages);}
We can also bind it by using Bind method a bit differently:
public void ConfigureServices(IServiceCollection services){ services.AddMvc(); var messages = new MessagesOptions(); Configuration.Bind("Messages", messages);}
This is really cool and we could even make a singleton service so we are able to use these values in our code.
However, there is support for this baked in Configuration framework. Read on.
Another way to get values from our Configuration:
public void ConfigureServices(IServiceCollection services){ services.AddMvc(); services.Configure<MessagesOptions>(Configuration.GetSection("Messages"));}
Now this means that we can useIOptions<MessagesOptions>
anywhere in our application.
IOptions
interface has only one member:
public interface IOptions<out TOptions> where TOptions : class, new(){ // // Summary: // The default configured TOptions instance, equivalent to Get(string.Empty). TOptions Value { get; }}
That means that Value will be an object of a class that we provided, in our case that isMessagesOptions.
I will make a simple Razor Page demonstrating usage of IOptions:
using IOptionsConfiguration.Configuration;using Microsoft.AspNetCore.Mvc.RazorPages;using Microsoft.Extensions.Options;namespace IOptionsConfiguration.Pages{ public class PartialSettings : PageModel { public PartialSettings(IOptions<MessagesOptions> iOptionsMessages) { Messages = iOptionsMessages.Value; } public string MainMessageFromConfig { get; set; } public MessagesOptions Messages { get; set; } public void OnGet() { } }}
Another thing we can do is to make a class that will match appsettings.json root object, not only parts of it. Meaning, all values from appsettings.json that have matching property within the class will map to those properties.
Let’s say we have the following appsettings.json:
{ "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Warning" } }, "CoolestFramework": "Sails.js", "MainMessage": "Welcome to the site!", "Messages": { "ShouldShowAlert": true, "AlertMessage": "This is conditional message.", "RegularMessage": "This is regular message." }}
And we wanna map “MainMessage” root value and “Messages” object and we are not interested in other keys.
We would have a class like this:
public class CbnSettings{ public MessagesOptions Messages { get; set; } public string MainMessage { get; set; }}public class MessagesOptions{ public string AlertMessage { get; set; } public string RegularMessage { get; set; } public bool ShouldShowAlert { get; set; }}
Now we can simply do map Configuration toCbnSettings:
public void ConfigureServices(IServiceCollection services){ services.AddMvc(); services.Configure<CbnSettings>(Configuration);}
This will enable usage ofIOptions<CbnSettings>
inside of our code.
For reloading configuration functionality to work, there are two things you need to have:
IOptionsSnapshot
instead ofIOptions
If you don’t fancy usingIOptionsSnapshot<CbnSettings>
in your code (you find it ugly or whatever is the reason), you can do this:
services.Configure<CbnSettings>(Configuration);services.AddScoped(sp => sp.GetService<IOptionsSnapshot<CbnSettings>>().Value);
After this, you can useCbnSettings settings
in your constructor.
public Index(CbnSettings settings){ MainMessageFromConfig = settings.MainMessage; Messages = settings.Messages;}
Whatever you decide on your project, I would just recommend to be consistent.
Why is ASP.NET Core good for Enterprise applications
ASP.NET Core Dependency Injection – Cannot consume scoped service
Hosting ASP.NET Core on Heroku (with Docker&CircleCI) for free
ASP.NET Core 2 – Global Model validation
ASP.NET Core – Unit testing IAuthorizationService and dependencies inside of your controller
ASP.NET Core – InvalidOperationException: Cannot find compilation library location for package ‘Microsoft.Win32.Registry’
Software Consultant interested and specialising in ASP.NET Core, C#, JavaScript, Angular, React.js.
Categories
Tags