Enrico
Enrico

Reputation: 6202

Read configuration List from appsettings.json

In my ASP.NET Core project, I have the appsettings.json where I define the SmtpCredentials section. This section is a json array of configuration. Each service has to send an email with a specific SMTP credentials and servers.

{
  "Logging": {
     "LogLevel": {
        "Default": "Debug",
        "Microsoft": "Warning",
        "Microsoft.Hosting.Lifetime": "Information",
        "Hangfire": "Debug"
     }
  },
  "AllowedHosts": "*",
  "SmtpCredentials": [
     {
        "Name": "Default",
        "MailFrom": "[email protected]",
        "Username": "[email protected]",
        "Password": "mypassword",
        "Server": "smtp-mail.outlook.com",
        "Port": 587,
        "EnableSSL": true
     },
     {
        "Name": "Learn",
        "MailFrom": "[email protected]",
        "Username": "[email protected]",
        "Server": "smtp-mail.outlook.com",
        "Port": 587,
        "EnableSSL": true
     }
  ],
  "Api": {
     "Endpoint": "https://localhost:44381"
  }

}

My issue is to read the configuration in the Startup.cs and inject it.

services.Configure<SmtpSettings>(Configuration.GetSection("SmtpCredentials")
        .Get<List<SmtpCredentialsSettings>>());
services.AddScoped(cfg => cfg.GetService<IOptions<SmtpSettings>>().Value);

In the injection, the settings are null. How can I read and inject this configuration?

Update

This is the SmtpSettings I refer to.

public class SmtpCredentialsSettings
{
    public string Name { get; set; }
    public string MailFrom { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string Server { get; set; }
    public int Port { get; set; }
    public bool EnableSSL { get; set; }
}

public class SmtpSettings
{
    public List<SmtpCredentialsSettings> SmtpCredentials { get; set; }
}

Upvotes: 0

Views: 1468

Answers (2)

Enrico
Enrico

Reputation: 6202

I saw this reply on Stackoverflow that is exactly the same issue I have. The solution is the following:

SmtpCredentialsSettings[] smtpCredentials = 
    Configuration.GetSection("SmtpCredentials")
                 .Get<SmtpCredentialsSettings[]>();
services.Configure<SmtpSettings>(option =>
{
    option.SmtpCredentials = smtpCredentials;
});
services.AddScoped(cfg => cfg.GetService<IOptions<SmtpSettings>>().Value);

Upvotes: 0

Nicola Biada
Nicola Biada

Reputation: 2800

I think the problem is the Json parsing. If I use :

services.Configure<SmtpSettings>(options => configuration.GetSection("SmtpSettings").Bind(options));

and change the appsettings.json to this:

"SmtpSettings": {
    "SmtpCredentials": [
      {
        "Name": "Default",
        "MailFrom": "[email protected]",
        "Username": "[email protected]",
        "Password": "mypassword",
        "Server": "smtp-mail.outlook.com",
        "Port": 587,
        "EnableSSL": true
      },
      {
        "Name": "Learn",
        "MailFrom": "[email protected]",
        "Username": "[email protected]",
        "Server": "smtp-mail.outlook.com",
        "Port": 587,
        "EnableSSL": true
      }
    ]
  }

it works as expected.

I haven't tried the scoped service, but from a controller like this:

[Route("api/[controller]")]
    [ApiController]
    public class TestController : ControllerBase
    {
        private readonly IOptions<SmtpSettings> _options;
        private readonly IConfiguration _configuration;

        public TestController(IOptions<SmtpSettings> options, IConfiguration configuration)
        {
            _options = options;
            _configuration = configuration;
        }
        
        [HttpGet("config")]
        public IActionResult GetConfig()
        {
            var result = _options.Value;
            return Ok(result);
        }
    }

it returns the corrected values.

{
"smtpCredentials": [
{
"name": "Default",
"mailFrom": "[email protected]",
"username": "[email protected]",
"password": "mypassword",
"server": "smtp-mail.outlook.com",
"port": 587,
"enableSSL": true
},
{
"name": "Learn",
"mailFrom": "[email protected]",
"username": "[email protected]",
"password": null,
"server": "smtp-mail.outlook.com",
"port": 587,
"enableSSL": true
}
]
}

Upvotes: 1

Related Questions