{"id":1023,"date":"2017-02-26T22:56:52","date_gmt":"2017-02-26T22:56:52","guid":{"rendered":"http:\/\/tpodolak.com\/blog\/?p=1023"},"modified":"2017-02-26T22:56:52","modified_gmt":"2017-02-26T22:56:52","slug":"asp-net-core-populating-ioptions-external-data-source","status":"publish","type":"post","link":"https:\/\/tpodolak.com\/blog\/2017\/02\/26\/asp-net-core-populating-ioptions-external-data-source\/","title":{"rendered":"Asp.NET Core &#8211; populating <i>IOptions&lt;T&gt;<\/i> from external data source"},"content":{"rendered":"<h3>1. Introduction<\/h3>\n<p>In <i>ASP.NET Core<\/i> <i>web.config<\/i> is no longer a proper place for storing application settings. New framework introduces the concept of a json based configuration and the default file which stores the settings now is <i>appsettings.json<\/i>. Here is a quick tutorial how to use new features.<\/p>\n<h3>2. Reading configuration<\/h3>\n<p>Let&#8217;s assume that our <i>appsettings.json<\/i> file looks as follows. <\/p>\n<pre lang=\"json\">\r\n{\r\n    \"Logging\": {\r\n        \"IncludeScopes\": false,\r\n        \"LogLevel\": {\r\n            \"Default\": \"Debug\",\r\n            \"System\": \"Information\",\r\n            \"Microsoft\": \"Information\"\r\n        }\r\n    },\r\n    \"AvailabilitySearchOptions\": {\r\n        \"FlexDaysIn\": 2,\r\n        \"FlexDaysOut\": 3\r\n    }\r\n}\r\n<\/pre>\n<p>Thanks to <i>ConfigurationBuilder<\/i> we can parse this config and later on materialize sections or entire file into strongly typed configuration classes. Let&#8217;s say we want to parse <i>AvailabilitySearchOptions<\/i> node to following class<\/p>\n<pre lang=\"csharp\">\r\npublic class AvailabilitySearchOptions\r\n{\r\n    public int FlexDaysIn { get; set; }\r\n\r\n    public int FlexDaysOut { get; set; }\r\n\r\n    public TimeSpan MinimumConnectionTime { get; set; }\r\n\r\n    public TimeSpan MinimumDepartureTime { get; set; }\r\n}\r\n<\/pre>\n<p>We can achieve that with following steps. First of all, we need to read entire configuration <\/p>\n<pre lang=\"csharp\">\r\npublic IConfigurationRoot Configuration { get; }\r\n\r\npublic Startup(IHostingEnvironment env)\r\n{\r\n    var builder = new ConfigurationBuilder()\r\n                        .SetBasePath(env.ContentRootPath)\r\n                        .AddJsonFile(\"appsettings.json\", optional: true, reloadOnChange: true)\r\n                        .AddJsonFile($\"appsettings.{env.EnvironmentName}.json\", optional: true)\r\n                        .AddEnvironmentVariables();\r\n    Configuration = builder.Build();\r\n}\r\n<\/pre>\n<p>And in the next step we have to register <i>IOptions&lt;AvailabilitySearchOptions&gt;<\/i> in the container using <i>services.Configure&lt;TOptions&gt;(IConfiguration section)<\/i> method<\/p>\n<pre lang=\"csharp\">\r\n\/\/ This method gets called by the runtime. Use this method to add services to the container.\r\npublic void ConfigureServices(IServiceCollection services)\r\n{\r\n    \/\/ Add framework services.\r\n    services.AddMvc();\r\n    services.Configure<AvailabilitySearchOptions>(Configuration.GetSection(\"AvailabilitySearchOptions\"));  \r\n}\r\n<\/pre>\n<p>Note <i>Configuration.GetSection(&#8220;AvailabilitySearchOptions&#8221;)<\/i> passed as argument to <i>services.Configure<\/i> method.<br \/>\nFrom now on we can access <i>AvailabilitySearchOptions<\/i> settings via <i>IOptions&lt;AvailabilitySearchOptions&gt;<\/i> interface, which you can easily inject into your classes.\t<\/p>\n<pre class=\"csharp\">\r\n[Route(\"api\/[controller]\")]\r\npublic class OptionsController : Controller\r\n{\r\n    private readonly IOptions<AvailabilitySearchOptions> availabilitySearchOptions;\r\n\r\n    public OptionsController(IOptions<AvailabilitySearchOptions> availabilitySearchOptions)\r\n    {\r\n        this.availabilitySearchOptions = availabilitySearchOptions;\r\n    }\r\n\r\n    public AvailabilitySearchOptions Get()\r\n    {\r\n        return availabilitySearchOptions.Value;\r\n    }\r\n}\r\n<\/pre>\n<h3>3. Populating <i>IOptions&lt;T&gt;<\/i> from external data source<\/h3>\n<p>From time to time, reading configuration just from JSON file might not be enough and for instance you would like to add additional configuration read from some external data source. Fortunately you don&#8217;t have to resign from the <i>IOptions&lt;T&gt;<\/i> class as it is possible to read additional data for literally any other source thanks to <i>IConfigureOptions&lt;T&gt;<\/i> class. All we have to do is to create a setup class which implements <i>IConfigureOptions&lt;T&gt;<\/i> interface<\/p>\n<pre class=\"csharp\">\r\npublic class AvailabilitySearchOptionsSetupService : IConfigureOptions<AvailabilitySearchOptions>\r\n{\r\n    private readonly ILogger<AvailabilitySearchOptionsSetupService> logger;\r\n    private readonly IReservationSettingsService reservationSettingsService;\r\n\t\r\n    public AvailabilitySearchOptionsSetupService(ILogger<AvailabilitySearchOptionsSetupService> logger ,IReservationSettingsService reservationSettingsService)\r\n    {\r\n        this.logger = logger;\r\n        this.reservationSettingsService = reservationSettingsService;\r\n    }\r\n\t\r\n    public void Configure(AvailabilitySearchOptions options)\r\n    {\r\n        this.logger.LogInformation($\"Calling first {typeof(IConfigureOptions<AvailabilitySearchOptions>)} service\");\r\n        options.MinimumConnectionTime = reservationSettingsService.GetMinimumConnectionTime();\r\n    }\r\n}\r\n<\/pre>\n<p>And then registering this class in our container<\/p>\n<pre lang=\"csharp\">\r\n\/\/ This method gets called by the runtime. Use this method to add services to the container.\r\npublic void ConfigureServices(IServiceCollection services)\r\n{\r\n    \/\/ Add framework services.\r\n    services.AddMvc();\r\n    services.Configure<AvailabilitySearchOptions>(Configuration.GetSection(\"AvailabilitySearchOptions\"));\r\n    services.AddSingleton<IConfigureOptions<AvailabilitySearchOptions>, AvailabilitySearchOptionsSetupService>();\r\n}\r\n<\/pre>\n<p>From now on, when value of <i>IOptions&lt;AvailabilitySearchOptions&gt;<\/i> is accessed for very first time, <i>Configure<\/i> method from <i>AvailabilitySearchOptionsSetupService<\/i> will be called and you will be able to set additional values for your settings. Note that values from <i>appsettings.json<\/i> will already be there.<br \/>\nIn addition, it is possible to have multiple implementations of <i>IConfigureOptions&lt;T&gt;<\/i> so if you want your setup to be split into multiple classes you are good to go.<br \/>\n\t<a href=\"\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/02\/asp-net-core-populating-ioptions-external-data-source\/multiple.png\" rel=\"attachment wp-att-1041\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/02\/asp-net-core-populating-ioptions-external-data-source\/multiple.png\" alt=\"multiple\" width=\"824\" height=\"540\" class=\"aligncenter size-full wp-image-1041\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/02\/asp-net-core-populating-ioptions-external-data-source\/multiple.png 824w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/02\/asp-net-core-populating-ioptions-external-data-source\/multiple-150x98.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2017\/02\/asp-net-core-populating-ioptions-external-data-source\/multiple-300x197.png 300w\" sizes=\"auto, (max-width: 824px) 100vw, 824px\" \/><\/a><br \/>\nSource code for this post can be found <a href=\"https:\/\/github.com\/tpodolak\/Blog\/tree\/master\/AspNetCoreInitializingOptions\">here<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Introduction In ASP.NET Core web.config is no longer a proper place for storing application settings. New framework introduces the concept of a json based configuration and the default file which stores the settings now is appsettings.json. Here is a quick tutorial how to use new features. 2. Reading configuration Let&#8217;s assume that our appsettings.json [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[317],"tags":[318],"class_list":["post-1023","post","type-post","status-publish","format-standard","hentry","category-asp-net-core","tag-asp-net-core"],"_links":{"self":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/1023","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/comments?post=1023"}],"version-history":[{"count":21,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/1023\/revisions"}],"predecessor-version":[{"id":1046,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/1023\/revisions\/1046"}],"wp:attachment":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/media?parent=1023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/categories?post=1023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/tags?post=1023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}