1

I have model for email setting

public class EmailSettingsModel {
    public string MailServer { get; set; }
    public int MailPort { get; set; }
    public string SenderName { get; set; }
    public string Sender { get; set; }
    public string Password { get; set; }
}

I put secret value in Azure Key vault

MailServer:smtp.gmail.com; MailPort:587; SenderName:SenderName; Sender:the.sender@gmail.com; Password:123!2019#

In the Startup.cs file, I put my code, register it with the run time:

public Startup(IConfiguration configuration) {
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services) {
    //this appSetting can return value from Azure Key Vault, the secret key.
    var appSetting = Configuration.GetValue<string>("AzureKeyVaultEmail");

    services.Configure<EmailSettingsModel>(Configuration.GetSection("AzureKeyVaultEmail"));
    services.AddSingleton<IEmailSender, EmailSender>();

    services.AddOptions();
    services.AddMvc();
}

For injection in class

public class EmailSender : IEmailSender
{
    private readonly EmailSettingsModel _emailSettings;

    public EmailSender (IOptions<EmailSettingsModel> emailSettings) {

        _emailSettings = emailSettings.Value;
    }
}

But _emailSettings always null. For '_emailSettings', it suppose return value

MailServer = smtp.gmail.com
MailPort = 587
SenderName = SenderName
Sender = the.sender@gmail.com
Password = 123!2019#

Why _emailSettings always return null ? Do I miss something ? I try to use this as reference

Daleman
  • 794
  • 8
  • 23

2 Answers2

1

From the code which is mentioned in the question, it was not explained if you have written the valid configuration for Azure key vault which would be something standard like below, hope you have added that.

var azureServiceTokenProvider = new AzureServiceTokenProvider();
                                var keyVaultClient = new KeyVaultClient(
                                    new KeyVaultClient.AuthenticationCallback(
                                        azureServiceTokenProvider.KeyVaultTokenCallback));

                                config.AddAzureKeyVault(
                                    vaultConfig.AzureVaultUrl,
                                    keyVaultClient,
                                    new DefaultKeyVaultSecretManager());

Also for reading complex object from key vault i would suggest you to write something like below:

services.AddSingleton<EmailSettingsModel >(sp =>
{
    var resultJson = Configuration.GetSection("AzureKeyVaultEmail").Value;
    return JsonConvert.DeserializeObject<EmailSettingsModel>(resultJson);
});

Also as i can see in the question , below string doesn't look like a valida json format:

MailServer:smtp.gmail.com; MailPort:587; SenderName:SenderName; Sender:the.sender@gmail.com; 

Please change it in a valid format and it should work.

Hope it helps.

Mohit Verma
  • 5,140
  • 2
  • 12
  • 27
  • Thx for giving effort with my code. I ignore including azure key vault configuration because it's already returned value. Actually, in AKV, it has 2 keys for dB connection string & email setting. Let's focus on 'Configuration.GetSection to JSON. Let me try & I'll be back to you soon. – Daleman Jan 09 '20 at 13:48
  • Sure, let me know how it goes. – Mohit Verma Jan 09 '20 at 13:49
  • I've tried some JSON formats and got error. I tried validate Json format through http://json2csharp.com. Eventually, I got Json format that return no error for EmailSetting to match with EmailSettingModel but the return of 'JsonConvert.DeserializeObject' still null. This is Json formaat that I put in AKV secrets and return null: { EmailSettingsModel: { MailServer: "smtp.gmail.com", MailPort: 587, SenderName: "SenderName", Sender: "The.sender@gmail.com", Password: "@!#$FASaswer" } } – Daleman Jan 10 '20 at 02:12
  • according to this link (https://www.newtonsoft.com/json/help/html/DeserializeObject.htm), I made modification the JSON ({ MailServer: "smtp.gmail.com", MailPort: 587, SenderName: "SenderName", Sender: "The.sender@gmail.com", Password: "@!#$FASaswer" }) and tried to get the value of JsonConvert.DeserializeObject(resultJson) as a variable. It works well but injection in EmailSender class still return null. – Daleman Jan 10 '20 at 04:23
1

In Startup.cs , I use the code below to inject EmailSettingsModel and add to services:

services.AddSingleton<EmailSettingsModel>(sp =>
{
    var resultJson = Configuration.GetSection("<your secret name in kv>").Value;
    return JsonConvert.DeserializeObject<EmailSettingsModel>(resultJson);
});

And in HomeController:

public class HomeController : Controller
{
    private readonly EmailSettingsModel emailSender;
    public HomeController(EmailSettingsModel _emailSender)
    {
        emailSender = _emailSender;
    }
    public IActionResult Index()
    {
        var a = emailSender.MailServer ;
        return View();
    }
}

And you will get the keyvault value. You could refer to this SO thread.

Joey Cai
  • 18,968
  • 1
  • 20
  • 30