Reputation: 135
I am developing a .Net 6.0 ASP.NET Core Web App in which appsettings.json
is edited for admin purpose after the app has started. The information to be edited looks like:
{
"Admin": {
"WhiteList": ["::1",.....]
},
....
which is modeled as
public class AdminOptions
{
public const string Admin = "Admin";
public string[] WhiteList { get; set; }
}
and configured in Program.cs
as follows:
...
ver builder = WebApplication.CreateBuilder(args);
builder.Services.Configuraion<AdminOptions>(
builder.Configuration.GetSection(AdminOptions.Admin));
AdminOptions
is constructor-injected to a Singleton service which looks like:
public class WhiteChecker: IWhiteChecker
{
private readonly IOptionsMonitor<AdminOptions> optionsMonitor;
public WhiteChecker(IOptionsMonitor<AdminOptions> monitor)
{
optionsMonitor = monitor;
}
.....[optionsMonitor.CurrentValue.WhiteList is consumed here].....
}
If appsettings.json
in the project root is edited, IOptionsMonitor.CurrentValue
returns the post-edit value of the pre-bound WhiteList
property in Admin
section, as expected.
However, if the one in AppContext.BaseDirectory
(which I believe is the right place) is edited, IOptionsMonitor
ignores.
I tried a change in WebApplicationBuilder.Environment.ContentRootPath
(which is set to the project root by default) to AppContext.BaseDirectory
before the WebApplicationBuilder
is built at Program.cs
, but the same result.
Is there any way to configure IOptionsMonitor
to respond to the change in appsettings.json
in Appcontext.BaseDirectory
? Or do I misunderstand anything?
UPDATE(10/11/2022)
My way of setting Environment.ContentRootPath
was wrong.
Wrong:
var builder = WebApplication.CreateBuilder(args);
builder.Environment.ContentRootPath = AppContext.BaseDirectory;
Correct:
var builder = WebApplication.CreteBuilder(new WebApplicationOptions
{
ContentRootPath = AppContext.BaseDirectory
});
After setting correctly, IOptionsMonitor
started to monitor the appsettings.json
in AppContext.BaseDirectory
.
The "Correct" version follows the way as instructed in ASP.NET CORE6.0 doc>Migration>3.1/5.0 Code to 6.0.
I'm not sure why the "Wrong" version does not work, but it may be due to:
The following variables are locked in early when initializing the host builders and can't be influenced by application config:
- Application name
- Environment name, for example Development,Production, and Staging
- Content root
- Web root ...
as described in ASP.NET CORE6.0 doc>Fundamentals>Configuration.
UPDATE(10/13/2022)
The behavior mentioned in the above quote is clearly reiterated at ASP.NET CORE6.0 doc>Migrations>5.0 to 6.0:
It's not possible to change any host settings such as app name, environment, or the content root after the creation of the WebApplicationBuilder.
The tricky part is that no exception is thrown if coded like the "Wrong" way above. It silently ignores the change by design.
Upvotes: 0
Views: 849
Reputation: 2325
The issue sounds like a non-issue according to the documentation provided by Microsoft. I quote from this page:
During development, the content root defaults to the project's root directory. This directory is also the base path for both the app's content files and the Web root. Specify a different content root by setting its path when building the host. For more information, see Content root.
Same page, different anchor:
The CreateDefaultBuilder method:
- Sets the content root to the path returned by GetCurrentDirectory.
What you see is the expected behavior: The project's root for development, and when deployed somewhere, whatever is set for working directory.
Upvotes: 1