Search code examples
c#asp.net-coreappsettings

Can't load options from appsettings in ASP.NET Core site using IOptions


I'm trying to load data from my appsettings file in an ASP.NET Core project. I've done it before, but now I can't get it to work. Furthermore, I'm trying to configure a section names Images and bind it against an object of type WorkImageOptions, which contains info about a collection of images.

I try to retrieve the values using IOptionsSnapshot, but it's always empty if, though there's data in the settings section.

Program.cs:

using SLT.Bohem63.Peachie.Config;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services
    .Configure<WorkImageOptions>(builder.Configuration.GetSection(WorkImageOptions.SectionName));

builder.Services.AddControllersWithViews();

WebApplication app = builder.Build();

app.UseRouting();
app.MapStaticAssets();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Bohem63}/{action=Index}/{id?}")
    .WithStaticAssets();

app.Run();

WorkImageOptions.cs:

public sealed class WorkImageOptions
{
    public IEnumerable<WorkImageInfo> Images { get; set; }

    public static string SectionName => "Images";
}

WorkImageInfo.cs:

namespace SLT.Bohem63.Peachie.Models.Data
{
    public interface IWorkImageInfo
    {
        string Filename { get; set; }
        string Title { get; set; }
        string Description { get; set; }
        int Likes { get; set; }
    }

    public sealed class WorkImageInfo : IWorkImageInfo
    {
        public string Filename { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public int Likes { get; set; } = 0;
    }
}

Retrieve options:

public class Bohem63Controller(IOptionsSnapshot<WorkImageOptions> options) : Controller { }

appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Images": {
    "filename": "pic1.jpg",
    "title": "",
    "description": "",
    "likes": 0
  }
}

Solution

  • With the current structure, appsettings.json has to look like this for it to work:

    "Images": {
      "Images": [
        {
          "filename": "foo.jpg",
          "title": "bar",
          "description": "baz",
          "likes": 42
        }
      ]
    }
    

    although I'd change things a bit by getting rid of the SectionName property and use nameof with the class name instead:

    builder.Services
        .Configure<WorkImageOptions>(builder.Configuration.GetSection(nameof(WorkImageOptions)));
    

    appsettings.json:

    "WorkImageOptions": {
      "Images": [
        {
          "filename": "foo.jpg",
          "title": "bar",
          "description": "baz",
          "likes": 42
        }
      ]
    }