0

I have a class like this:

public class GameSettingOptions
{
    public const string GameSettings = "GameSettings";

    public int gameId { get; set; }
    public string iconSize { get; set; }
    public int sortOrder { get; set; }
    public string[] chips { get; set; }
}

and a GameSettingsOptions.json file like this:

{
  "GameSettings": [
    {
      "gameId": 1,
      "iconSize": "big",
      "sortOrder": 6
    },
    {
      "gameId": 2,
      "iconSize": "small",
      "sortOrder": 4
    },
    {
      "gameId": 3,
      "iconSize": "medium",
      "sortOrder": 2
    },
    {
      "gameId": 4,
      "iconSize": "small",
      "sortOrder": 5
    },
    {
      "gameId": 5,
      "iconSize": "small",
      "sortOrder": 8,
      "chips": []
    },
    {
      "gameId": 6,
      "iconSize": "small",
      "sortOrder": 7
    },
    {
      "gameId": 7,
      "iconSize": "big",
      "sortOrder": 1,
      "chips": []
    },
  ]
}

I am trying to use the Options pattern to return these game settings through a controller like this:

public class GameSettingsControllers : ControllerBase
{
    private readonly GameSettingOptions _gameSettingOptions;

    public GameSettingsControllers(IOptions<GameSettingOptions> gameSettingOptions)
    {
        _gameSettingOptions = gameSettingOptions.Value;
    }

    public object GetGameSettings()
    {
        return Content ($"gameId: {_gameSettingOptions.gameId}" + $"iconSize: {_gameSettingOptions.iconSize}"
            + $"sortOrder: {_gameSettingOptions.sortOrder}" + $"chips: {_gameSettingOptions.chips}");
    }
}

This is how I set up my Startup.cs file to use dependency injection on the IOptions class:

public Startup(IConfiguration configuration, IHostingEnvironment environment)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(environment.ContentRootPath)
        .AddJsonFile("GameSettingOptions.json", optional: true, reloadOnChange: true);
    Configuration = builder.Build();
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddCors(c =>
    {
        c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
    });
    services.Configure<GameSettingOptions>(options => Configuration.GetSection(GameSettingOptions.GameSettings).Bind(options));
}

However the controller always returns null. I have no idea if I am using the wrong method inside the Configuration interface or not. The problem seems to lie in the binding between the JSON file and the GameSettingOptions class. Therefore currently the API keeps returning this:

gameId: 0iconSize: sortOrder: 0chips: 

What I get from debugging what the Configuration returns enter image description here

Callum Watkins
  • 2,844
  • 4
  • 29
  • 49
Noelia
  • 89
  • 10
  • Check with `services.Configure(options => Configuration.GetSection(GameSettingOptions.GameSettings).Bind(options));` in `ConfigureServices` while add configuration. Also, you should add the file in Progam.Cs file in `CreateHostBuilder`. If done in `CreateHostBuilder` then you don't need to rebuild the build the configuration object in `Startup` class. – user1672994 Jan 18 '21 at 03:34
  • @user1672994 I used the Binding method that you provided and it seems like they are binding to the right file already. Somehow the controller still returns null so I guess it is something about my controller returning. Plus the Configuration returns the data in the Key Value Pair so each object in the json file turns into 3 or 4 key-value pair like this. Is this the right approach? – Noelia Jan 18 '21 at 04:03
  • @user1672994 this is the picture https://i.stack.imgur.com/jbJ0P.png – Noelia Jan 18 '21 at 04:06
  • 1
    `GameSettings` is array in your config. You can create a new class which would have collection of `GameSettingOptions` property; give the name as `GameSettings`; then bind and inject the new class. – user1672994 Jan 18 '21 at 04:19
  • Seems that not a supported feature. Check [this](https://www.codewrecks.com/blog/index.php/2020/03/14/net-core-configuration-array-with-bind/) and [this](https://rimdev.io/avoiding-aspnet-core-configuration-pitfalls-with-array-values/). Also also list some workaround like storing as string and deserialize it as needed. – user1672994 Jan 18 '21 at 04:56
  • Having just `services.Configure(Configuration.GetSection("..."))` works for me. Though I haven't tried to bind an array directly like that. You probably need `IOptions>`. – Jeremy Lakeman Jan 18 '21 at 05:24
  • `services.Configure>(Configuration.GetSection("..."));` and `IOptions` should be changed to `IOptions>` – Chetan Jan 18 '21 at 05:40
  • @ChetanRanpariya how should I return it as JsonResult? – Noelia Jan 18 '21 at 07:06
  • You want to return it from Controller action as JsonResult? You can store `gameSettingOptions.Value` to a class level variable of type `List` and return as `return Json(_gameSettingOptions, JsonRequestBehavior.Get);` – Chetan Jan 18 '21 at 07:19

0 Answers0