I want to inject some email configuration data from database to config class named AuthMessageSenderOptions, this class has following properties:
public class AuthMessageSenderOptions
{
    public int PortNumber { get; set; }
    public string SmtpServer { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
}
For injecting configuration detail in appsettings.json to AuthMessageSenderOptions class, I use this piece of code in Startup.cs:
services.Configure<AuthMessageSenderOptions>(Configuration.GetSection("SMTP"));
Now my question is:
How can read this data from database instead of appsettings.json and inject them to my AuthMessageSenderOptions class for future use?
You can create a custom configuration source by creating a class that implements the interface IConfigurationSource and implementing your custom configuration provider by inheriting from ConfigurationProvider.
First, create a config source to initialize the data source with entity framework:
public class CustomMailConfigSource: IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _dbOptions;
    public CustomMailConfigSource(Action<DbContextOptionsBuilder> dbOptions)
    {
        _dbOptions = dbOptions;
    }
    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new CustomMailConfigProvider(_dbOptions);
    }
}
Then, implement the custom config provider:
public class CustomMailConfigProvider: ConfigurationProvider
{
    public CustomMailConfigProvider(Action<DbContextOptionsBuilder> dbOptions)
    {
        DbOptions = dbOptions;
    }
    Action<DbContextOptionsBuilder> DbOptions { get; }
    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<ConfigurationContext>();
        DbOptions(builder);
        using (var dbContext = new ConfigurationContext(builder.Options))
        {
            dbContext.Database.EnsureCreated();
            //Modify this to suit your needs, here is an example assuming you have a table called AuthMessageSenderOption with the same fields as the class in your question
            var authMessageSender = db.Context.AuthMessageSenders.FirstOrDefault();
            // You should add some code here to check if the settings exist and provide defaults if necessary
            Data = new Dictionary<string, string>
            {
                { "PortNumber", authMessageSenderOption.PortNumber},
                { "SmtpServer", authMessageSenderOption.SmtpServer },
                { "UserName", authMessageSenderOption.UserName},
                { "Password", authMessageSenderOption.Password}
            };
        }
    }
}
Finally, you need to register the custom configuration provider.
Create an IConfigurationBuilder extension:
public static class CustomProviderExtensions
{
    public static IConfigurationBuilder AddCustomMailConfigProvider(
        this IConfigurationBuilder builder, Action<DbContextOptionsBuilder> dbOptions)
    {
        return builder.Add(new CustomMailConfigSource(dbOptions));
    }
}
Register the provider in your Main() method using the extension you just created:
var config = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        // Add "appsettings.json" to bootstrap EF config.
        .AddJsonFile("appsettings.json")
        // Add the EF configuration provider, which will override any
        // config made with the JSON provider.
        .AddCustomMailConfigProvider(dbOptions =>
            dbOptions .UseSqlServer(connectionStringConfig.GetConnectionString(
                "DefaultConnection"))
        )
        .Build();
References:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?tabs=basicconfiguration
https://docs.microsoft.com/en-us/dotnet/api/Microsoft.Extensions.Configuration.ConfigurationProvider?view=aspnetcore-2.0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With