How to load appsetting.json section into Dictionar

2020-02-24 07:13发布

I am familiar w/ loading an appsettings.json section into a strongly typed object in .NET Core startup.cs. For example:

public class CustomSection 
{
   public int A {get;set;}
   public int B {get;set;}
}

//In Startup.cs
services.Configure<CustomSection>(Configuration.GetSection("CustomSection"));

//Inject an IOptions instance
public HomeController(IOptions<CustomSection> options) 
{
    var settings = options.Value;
}

I have an appsettings.json section who's key/value pairs will vary in number and name over time. Therefore, it's not practical to hard code property names in a class since new key/value pairs would require a code change in the class. A small sample of some key/value pairs:

"MobileConfigInfo": {
    "appointment-confirmed": "We've booked your appointment. See you soon!",
    "appointments-book": "New Appointment",
    "appointments-null": "We could not locate any upcoming appointments for you.",
    "availability-null": "Sorry, there are no available times on this date. Please try another."
}

Is there a way to load this data into a MobileConfigInfo Dictionary object and then use the IOptions pattern to inject MobileConfigInfo into a controller?

9条回答
Lonely孤独者°
2楼-- · 2020-02-24 07:36

I use the way below:

appsettings.json:

  "services": {
      "user-service": "http://user-service:5000/",
      "app-service": "http://app-service:5000/"
  } 

startup.cs:

  services.Configure<Dictionary<string, string>>(Configuration.GetSection("services"));

Usage:

private readonly Dictionary<string, string> _services;
public YourConstructor(IOptions<Dictionary<string, string>> servicesAccessor)
{
    _services = servicesAccessor.Value;
}
查看更多
家丑人穷心不美
3楼-- · 2020-02-24 07:39

The only thing that worked for me (ASP.NET Core 3.0) was to add the following to the ConfigureServices method of Startup.cs:

services.Configure<Dictionary<string, string>>(dict => Configuration.GetSection("MySectionName").GetChildren().ToList().ForEach(c => dict[c.Key] = c.Value));
查看更多
ら.Afraid
4楼-- · 2020-02-24 07:41

Go with this structure format:

"MobileConfigInfo": {
    "Values": {
       "appointment-confirmed": "We've booked your appointment. See you soon!",
       "appointments-book": "New Appointment",
       "appointments-null": "We could not locate any upcoming appointments for you.",
       "availability-null": "Sorry, there are no available times on this date. Please try another."
 }
}

Make your setting class look like this:

public class CustomSection 
{
   public Dictionary<string, string> Values {get;set;}
}

then do this

services.Configure<CustomSection>((settings) =>
{
     Configuration.GetSection("MobileConfigInfo").Bind(settings);
});
查看更多
我想做一个坏孩纸
5楼-- · 2020-02-24 07:45

As an example of more complex binding in ASP.Net Core 2.1; I found using the ConfigurationBuilder .Get<T>() method far easier to work with, as per the documention.

ASP.NET Core 1.1 and higher can use Get, which works with entire sections. Get can be more convenient than using Bind.

I bound the configuration in my Startup method.

private Config Config { get; }

public Startup(IConfiguration Configuration)
{
    Config = Configuration.Get<Config>();
}

This binds the appsettings file:

{
    "ConnectionStrings": {
        "Accounts": "Server=localhost;Database=Accounts;Trusted_Connection=True;",
        "test": "Server=localhost;Database=test;Trusted_Connection=True;",
        "Client": "Server=localhost;Database={DYNAMICALLY_BOUND_CONTEXT};Trusted_Connection=True;",
        "Support": "Server=localhost;Database=Support;Trusted_Connection=True;"
    },
    "Logging": {
        "IncludeScopes": false,
        "LogLevel": {
            "Default": "Debug",
            "System": "Information",
            "Microsoft": "Information"
        }
    },
    "Plugins": {
        "SMS": {
            "RouteMobile": {
                "Scheme": "https",
                "Host": "remote.host",
                "Port": 84567,
                "Path": "/bulksms",
                "Username": "username",
                "Password": "password",
                "Source": "CompanyName",
                "DeliveryReporting": true,
                "MessageType": "Unicode"
            }
        },
        "SMTP": {
            "GenericSmtp": {
                "Scheme": "https",
                "Host": "mail.host",
                "Port": 25,
                "EnableSsl": true,
                "Username": "smtpuser@mail.host",
                "Password": "password",
                "DefaultSender": "noreply@companyname.co.uk"
            }
        }
    }
}

Into this configuration structure:

[DataContract]
public class Config
{
    [DataMember]
    public Dictionary<string, string> ConnectionStrings { get; set; }
    [DataMember]
    public PluginCollection Plugins { get; set; }
}

[DataContract]
public class PluginCollection
{
    [DataMember]
    public Dictionary<string, SmsConfiguration> Sms { get; set; }
    [DataMember]
    public Dictionary<string, EmailConfiguration> Smtp { get; set; }
}

[DataContract]
public class SmsConfiguration
{
    [DataMember]
    public string Scheme { get; set; }
    [DataMember]
    public string Host { get; set; }
    [DataMember]
    public int Port { get; set; }
    [DataMember]
    public string Path { get; set; }
    [DataMember]
    public string Username { get; set; }
    [DataMember]
    public string Password { get; set; }
    [DataMember]
    public string Source { get; set; }
    [DataMember]
    public bool DeliveryReporting { get; set; }
    [DataMember]
    public string Encoding { get; set; }
}

[DataContract]
public class EmailConfiguration
{
    [DataMember]
    public string Scheme { get; set; }
    [DataMember]
    public string Host { get; set; }
    [DataMember]
    public int Port { get; set; }
    [DataMember]
    public string Path { get; set; }
    [DataMember]
    public string Username { get; set; }
    [DataMember]
    public string Password { get; set; }
    [DataMember]
    public string DefaultSender { get; set; }
    [DataMember]
    public bool EnableSsl { get; set; }
}
查看更多
兄弟一词,经得起流年.
6楼-- · 2020-02-24 07:47

For simple (perhaps microservice) applications you can just add it it as a singleton Dictionary<string, string> and then inject it wherever you need it:

var mobileConfig = Configuration.GetSection("MobileConfigInfo")
                    .GetChildren().ToDictionary(x => x.Key, x => x.Value);

services.AddSingleton(mobileConfig);

And the usage:

public class MyDependantClass
{
    private readonly Dictionary<string, string> _mobileConfig;

    public MyDependantClass(Dictionary<string, string> mobileConfig)
    {
        _mobileConfig = mobileConfig;
    }

    // Use your mobile config here
}
查看更多
够拽才男人
7楼-- · 2020-02-24 07:49

By far the simplest method would be to define your configuration class to inherit from the Dictionary type you want to support.

public class MobileConfigInfo:Dictionary<string, string>{
}

Then your startup and dependency injection support would be exactly the same as for any other configuration type.

查看更多
登录 后发表回答