DEV Community

Ahmed Shah
Ahmed Shah

Posted on • Edited on • Originally published at dev.to

Introduction to IOptions Pattern in .Net.

Options pattern in .NET core is used to provide strongly type classes to access appsettings from the application or vault settings defined in the cloud. It provides encapsulation for that settings to be dependent on configured class and separated from other settings. These strongly typed classes can be created and can be validated across various services lifetime. we can configure Options pattern using three interfaces provided by .NET core.

  1. IOptions
  2. IOptionsSnapshot
  3. IOptionsMonitor

we will learn about these 3 interfaces how they can be used, what's the differences between them and how to validate them. Lets start.

IOptions

  • We can only Read the configuration when app has started.
  • Registered as singleton.
  • Does not suppord Named Options.

IOptionsSnapshot

  • we can modify the configuration on each request.
  • Registered as Scoped.
  • Support Named Options

IOptionsMonitor

  • we can modify the configuration on each request.
  • Registered as singleton.
  • Support Named Options
  • OnChange Method is used to listen if any value has been changed in settings.(OnChange returns an object that implements IDisposable that you need to dispose)
  • Please Read About Performance issues on official Microsoft documentation link .

we will talk about Named Options and Typed Options later.

lets update our default appsettings file with company settings with name, address and zip code.



{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "Company": {
    "Name": "Company 1",
    "Address": "Robert Robertson, 1234 NW Bobcat Lane, St. Robert, MO 65584-5678",
    "ZipCode": 75780
  },
  "AllowedHosts": "*"
}



Enter fullscreen mode Exit fullscreen mode

now create a C# class that matches our appsettings for companies the was defined before.



    public class CompanyOptions
    {
        public const string Options = "Company";

        public string Name { get; set; } = String.Empty;
        public string Address { get; set; } = string.Empty;
        public int ZipCode { get; set; } 
        public DateTime CreationDate { get; set; } = DateTime.UtcNow;

    }


Enter fullscreen mode Exit fullscreen mode

Lets access our Company Settings in controller using IOptions Interface. we will use the all 3 Interface provided by .NET in our controller constructor and access them in our http request to see the results.



using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

namespace Options_Pattern.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly CompanyOptions _companyIOptions;
        private readonly CompanyOptions _companyIOptionsSnapshot;
        private readonly CompanyOptions _companyIOptionsMonitor;


        public WeatherForecastController(IOptions<CompanyOptions> companyIOptions,
            IOptionsSnapshot<CompanyOptions> companyIOptionsSnapshot,
            IOptionsMonitor<CompanyOptions> companyIOptionsMonitor)
        {
            _companyIOptions = companyIOptions.Value;
            _companyIOptionsSnapshot = companyIOptionsSnapshot.Value;
            _companyIOptionsMonitor = companyIOptionsMonitor.CurrentValue;
        }
        [HttpGet("[action]")]
        public IActionResult GetOptionsPattern()
        {
            var optionResponse = new 
            {
                IOptions = _companyIOptions.Name,
                IOptionsSnapShot = _companyIOptionsSnapshot.Name,
                IOptionsMonitor = _companyIOptionsMonitor.Name,
                CreationDate=_companyIOptions.CreationDate
            };
            return Ok(optionResponse);
        }

    }
}


Enter fullscreen mode Exit fullscreen mode

You can see in the above code IOptionsMonitor is accessed using CurrentValue instead of Value because we can listen to OnChange if some value is changed in our settings.so we can perform other actions if required. Now lets run your project and see what's returned by GetOptionsPattern method in postman.

Image

the default appsettings values has been returned. lets change the appsettings value while our project is running. we will change the name of company from Company 1 to Company 1 has been updated save the appsettings file and run the postman request again. we can see the IOptions is not being updated but iOptionsSnapShot , IOptionsMonitor values has been updated.

Image

we can also perform some action in IOptionsMonitor OnChange when any value has been updated. Now will update the company name write a into default .NET console the company name and update date then compare it with out postman request. let make some changes into out controller now the code looks like this now.



using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

namespace Options_Pattern.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly CompanyOptions _companyIOptions;
        private readonly CompanyOptions _companyIOptionsSnapshot;
        private readonly CompanyOptions _companyIOptionsMonitor;


        private string CompanyName=string.Empty;
        public WeatherForecastController(IOptions<CompanyOptions> companyIOptions,
            IOptionsSnapshot<CompanyOptions> companyIOptionsSnapshot,
            IOptionsMonitor<CompanyOptions> companyIOptionsMonitor)
        {
            _companyIOptions = companyIOptions.Value;
            _companyIOptionsSnapshot = companyIOptionsSnapshot.Value;
            _companyIOptionsMonitor = companyIOptionsMonitor.CurrentValue;
            //listen to onchange and call our private OnComapnyValueChange method
            companyIOptionsMonitor.OnChange(updatedsettings => OnComapnyValueChange());
        }

        [HttpGet("[action]")]
        public IActionResult GetOptionsPattern()
        {
            var optionResponse = new 
            {
                IOptions = _companyIOptions.Name,
                IOptionsSnapShot = _companyIOptionsSnapshot.Name,
                IOptionsMonitor = _companyIOptionsMonitor.Name,
                CreationDate= _companyIOptionsMonitor.CreationDate
            };
            CompanyName = _companyIOptionsMonitor.Name;
            Console.WriteLine(CompanyName);
            return Ok(optionResponse);
        }
        private void OnComapnyValueChange()
        {

            Console.WriteLine($"{CompanyName} is called from OnValueChange Method{_companyIOptionsMonitor.CreationDate}");

        }

    }
}


Enter fullscreen mode Exit fullscreen mode

reload the project again send a postman request to load over options settings which remains the same as before, also observe the console default value of companyname is being printed there without date as seen below.

Image

lets update companyname in appsettings and save it. now we can see without sending any request it prints to the console twice due to (the underlying file watcher triggering multiple times for the same change. The second call to Watch sometimes fires immediately because of this) further read Link. The OnCompanyValueChange is fired due to IOptionsMonitor.OnChange() without sending any request. its just monitoring the change and we are listening to it.

In the upcoming article we will talk about validation in IOptions Patten and Difference Between Named and Typed Options .

Top comments (2)

Collapse
 
artydev profile image
artydev

Thank you :-)

Collapse
 
ahmedshahjr profile image
Ahmed Shah

Thanks @artydev please follow the upcoming series also there will be in depth review of
name and typed IOptions
validation in IOptions in detail