Passing IOptions into .Net core middleware class for json config retrieval

10,803

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

  1. Create the settings files - mySettings.json - with the contents
{
  "MySettings": {
    "Name": "Some Name from config",
    "Description": "Some Description from config"
  }
}
  1. 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)

  1. 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.

  1. Create the interface IMySettingsService
namespace SettingsApp.Services
{
    public interface IMySettingsService
    {
        string GetName();
    }
}

Note: I use the namespace SettingsApp.Services for this.

  1. 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;
        }
    }
}
  1. 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>();
  1. 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();
    }

...
  1. See the results:

Home controller constructor Inside the action

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);
Share:
10,803
iKnowNothing
Author by

iKnowNothing

Updated on June 15, 2022

Comments

  • iKnowNothing
    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?