简体   繁体   中英

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

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?

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:

家庭控制器构造函数 在行动里面

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM