Passing IOptions into .Net core middleware class for json config retrieval
Solution 1
Few points:
- Constructor is missing in the mentioned class - MysettingsService
- Did you register the implementation of IMysettingsService in Startup class?
- While registering the implementation, you can initialize the MysettingsService, like below:
services.AddSingleton<IMysettingsService, MysettingsService >(i => new MysettingsService ());
Follow these steps:
- Make sure that you have registered your JSON file - mysettings.json - in ConfigurationBuilder
-
Define MySettings
public class MySettings { public string Name { get; set; } public string Description { get; set; } }
-
Define MySettingsService
public class MySettingsService : IMySettingsService { private readonly MySettings mySettings; public MySettingsService (IOptions<MySettings> _mySettings) { mySettings = _mySettings.Value; } public string GetName() { return mySettings.Name; } }
-
In Startup
services.Configure<MySettings>(this.Configuration.GetSection("MySettings")); services.AddSingleton<IMySettingsService, MySettingsService >();
EDITED -- I am including the implementation for you to follow
I have created a sample application and it works for me; Please follow the steps below:
Few details.
My application name is: SettingsApp
- Create the settings files -
mySettings.json
- with the contents
{ "MySettings": { "Name": "Some Name from config", "Description": "Some Description from config" } }
- Configure it in the
Startup
public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("mySettings.json", true, reloadOnChange: true) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); if (env.IsDevelopment()) { // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately. builder.AddApplicationInsightsSettings(developerMode: true); } Configuration = builder.Build(); }
See the line:
.AddJsonFile("mySettings.json", true, reloadOnChange: true)
- Create
MySettings
object to hold the settings
namespace SettingsApp.Initialisations { public class MySettings { public string Name { get; set; } public string Description { get; set; } } }
Note: I use the namespace SettingsApp.Initialisations
to keep this file. You can choose any based on your application structure.
- Create the interface
IMySettingsService
namespace SettingsApp.Services { public interface IMySettingsService { string GetName(); } }
Note: I use the namespace SettingsApp.Services
for this.
- Implement the interface -
IMySettingsService
using SettingsApp.Initialisations; using Microsoft.Extensions.Options; namespace SettingsApp.Services { public class MySettingsService : IMySettingsService { private readonly MySettings mySettings; public MySettingsService(IOptions<MySettings> _mySettings) { mySettings = _mySettings.Value; } public string GetName() { return mySettings.Name; } } }
- Add the options and let the system know your implementation in
Startup.ConfigureServices
method
// This method gets called by the run time. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // Options services.AddOptions(); services.Configure<MySettings>(this.Configuration.GetSection("MySettings")); services.AddSingleton<IMySettingsService, MySettingsService>(); // Add framework services. services.AddApplicationInsightsTelemetry(Configuration); services.AddMvc(); }
Note to include the required using's.
Check the code below on how this is done:
// Options services.AddOptions(); services.Configure<MySettings>(this.Configuration.GetSection("MySettings")); services.AddSingleton<IMySettingsService, MySettingsService>();
- Use the implementation (I am using the
HomeController
for testing.)
public class HomeController : Controller { private IMySettingsService mySettingsService; public HomeController(IMySettingsService settingsService) { mySettingsService = settingsService; } public IActionResult Index() { // Get the settings var name = mySettingsService.GetName(); return View(); } ...
- See the results:
Solution 2
In newer version of .NET above binding method does not work anymore.
I have created an extension method that works:
public static void AddSettings<T>(this IServiceCollection serviceCollection, IConfiguration configuration) where T : class, new()
{
var settings = new T();
configuration.Bind(typeof(T).Name, settings);
serviceCollection.AddSingleton(settings);
}
Use it like this:
services.AddSettings<LoggingSettings>(configuration);
Full example:
string pathToConfigFile = "c:\\config.json";
IConfiguration configuration = new ConfigurationBuilder()
.AddJsonFile(pathToConfigFile, optional: false, reloadOnChange: true)
.Build();
var services = new ServiceCollection()
services.AddSingleton(configuration);
services.AddSettings<ConnectionSettings>(configuration);
services.AddSettings<LoggingSettings>(configuration);
services.AddSettings<AutoCreateSettings>(configuration);
iKnowNothing
Updated on June 15, 2022Comments
-
iKnowNothing almost 2 years
I'm trying to use strongly typed json config settings as per the Options pattern in .net core. All examples so far show how easy it is to inject the strongly typed settings class into a controller but I need to use it in a middleware class (Very similar to this question but I'm no further forward after trying it that way).
So, the setup:
mysettings.json
{ "MySettings": { "Name": "Some Name from config", "Description": "Some Description from config" } }
mysettings.cs
public class MySettings { public string Name { get; set; } = "Default name"; public string Description { get; set; } = "Default description"; }
startup.cs
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); // Add functionality to inject IOptions<T> services.AddOptions(); // Add our Config object so it can be injected services.Configure<MySettings>(Configuration.GetSection("MySettings")); services.AddSingleton<IMySettingsService, MySettingsService>(); }
MysettingsService.cs
public class MysettingsService : IMysettingsService { private MySettings mySettings { get; set; } public MysettingsService (MySettings _mySettings) { mySettings = _mySettings.value; } public string GetName() { return mySettings.Name; } }
How do I go about instantiating MysettingsService.cs and injecting an
IOptions<MySettings>
into the class constructor so I can call the GetName method?