Is there a way to reference an appsettings value within the Serilog section in appsettings?

130 views Asked by At

Using Serilog.Settings.Configuration (and presumably Serilog.Expressions) is it possible to reference another appsettings value? I'm trying to dynamically set endpointUrl below without duplicating the BaseUrl value or specifying the value outside of appsettings.

Serilog.Settings.Configuration has includes a section on their ReadMe around IConfiguration parameter, but it doesn't show an example assuming it's talking about what I'm referring to.

I tried the following solutions and none of them correctly set the value, except for the hard coded-duplicate approach.

"App": {
  "BaseUrl": "https://localhost:1234"
},
"Serilog": {
  "Using": [ "Serilog.Sinks.BrowserConsole", "Serilog.Sinks.BrowserHttp", "Serilog.Expressions" ],
  "WriteTo": [
    {
      "Name": "BrowserHttp",
      "Args": {
        // This works
        //"endpointUrl": "https://localhost:1234/ingest"

        // These do not work:
        //"endpointUrl": "{Concat(App.BaseUrl, '/ingest')}"
        //"endpointUrl": "{App.BaseUrl}/ingest"
        //"endpointUrl": "{App:BaseUrl}/ingest"
        //"endpointUrl": "{BaseUrl}/ingest"
        //"endpointUrl": "{AppSettings:App:BaseUrl}/ingest"
        //"endpointUrl": "App.BaseUrl/ingest"
      }
    }
  ]
}
1

There are 1 answers

0
Ryan On

You can use IServiceCollection.PostConfigure<TOptions>() to edit your options after being bound from configuration provider.

Options sample:

public class BaseOptions
{
    public const string SectionName = nameof(BaseOptions);
    
    public string BaseUrl { get; set; }
}



public class DerivedOptions
{
    public const string SectionName = nameof(DerivedOptions);
    
    public string AuthPath { get; set; }
}

Config sample:

{  
  "BaseOptions": {
    "BaseUrl": "https://localhost:5999"
  },
  "DerivedOptions": {
    "AuthPath": "/auth/login"
  }
}

Configuring:

var config = builder.Configuration;
var baseOptions = config.GetSection(BaseOptions.SectionName).Get<BaseOptions>();
var baseUrl = baseOptions.BaseUrl;

builder.Services.Configure<BaseOptions>(builder.Configuration.GetSection(BaseOptions.SectionName));
builder.Services.Configure<DerivedOptions>(builder.Configuration.GetSection(DerivedOptions.SectionName))
    .PostConfigure<DerivedOptions>(x => x.AuthPath =  baseUrl + x.AuthPath);

Usage:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly DerivedOptions _options;

    public HomeController(ILogger<HomeController> logger, IOptions<DerivedOptions> options)
    {
        _logger = logger;
        _options = options.Value;
    }

    public IActionResult Index()
    {
        return View(_options);
    }
}

This works, as you can see:

debug options value