'.NET 5 to .NET 6 migration - How to fix appsettings.json data being read as NULL after migration? Dependency injection not working

In .NET 5 we have some settings that are read from the appsettings.json file. Now that we have migrated the code from .NET 5 to .NET 6 the model we created to hold the application settings is showing as null. All of the code is building and running without errors until we get the null error reading the appsettings.json file.

Everything was working in .NET 5. We have updated the Program.cs file, deleted the Startup.cs file, updated the project file, and updated all the Nuget packages. The suspicion is that there is something wrong with the services configuration in the Program.cs file for the settings retrieval, but we have found no solution yet.

Program.cs file:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<IAPPRepository, APPRepository>();
builder.Services.AddHttpContextAccessor();
builder.Services.Configure<AppSettings>(options => builder.Configuration.GetSection("APPSettings"));


var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

AppSettings.cs model file:

namespace APP_2
{
    public class AppSettings
    {
        public List<string> Uics { get; set; }
        public List<string> InvoiceTypes { get; set; }
        public List<string> InvoiceEntityTypes { get; set; }
        public List<Option> PeriodOptions { get; set; }
        public List<Option> MonthOptions { get; set; }
        public List<string> ConnectionStrings { get; set; }

    }
}

PageForm.cs model file:

namespace APP_2.Pages.FormModels
{
    public class InvoiceSelectionForm
    {
        private readonly IOptions<APPSettings> _APPSettings;
        public InvoiceSelectionForm(IOptions<APPSettings> APPSettings)
        {
            _APPSettings = APPSettings;
            InvoiceTypes = _APPSettings.Value.InvoiceTypes;
            InvoiceEntityTypes = _APPSettings.Value.InvoiceEntityTypes;
            MonthOptions = _APPSettings.Value.MonthOptions;
            PeriodOptions = _APPSettings.Value.PeriodOptions;
        }

        public string InvoiceEntityType { get; set; }
        public string InvoiceType { get; set; }
        public string FiscalYear { get; set; }
        public bool UsePeriod { get; set; }
        public string FiscalPeriod { get; set; }
        public List<string> InvoiceTypes { get; set; }
        public List<string> InvoiceEntityTypes { get; set; }
        public List<Option> PeriodOptions { get; set; }
        public List<Option> MonthOptions { get; set; }
        public List<string> FiscalYears { get; set; } = Enumerable.Range(2012, DateTime.Now.Year - 2010).Reverse().Select(n => n.ToString()).ToList();
        public List<Option> SelectedInvoiceEntityTypes { get; set; } = new List<Option>();
        public List<Option> AvailableInvoiceEntityTypes { get; set; } = new List<Option>();

    }
}

PageCode.cs file:

namespace APP_2.Pages
{
    public partial class InvoiceSelection
    {        

        private IOptions<APPSettings> APPSettings { get; set; }

        protected override void OnInitialized()
        {
            form = new InvoiceSelectionForm(APPSettings);
 
        }
}


Solution 1:[1]

The wrong overload is being invoked to configure the options here

//...
builder.Services.Configure<AppSettings>(options => builder.Configuration.GetSection("APPSettings"));
//...

Pass the section directly and not a configuration delegate

//...

builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("APPSettings"));

//...

This should fix the issue for PageForm.cs where the option will be injected correctly.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tyson Gibby