Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a POCO object to access an array of options in the appsettings.json file (ASP.NET 5)

I am using ASP.NET 5 and I want to use POCO classes to access my appsettings.json file. This file looks like this:

{
  "Data": {
        "ErpSystemConnection": {
            "ConnectionString": "[myConnectionString]"
        }
  },
    "Logging": {
        "IncludeScopes": false,
        "LogLevel": {
            "Default": "Verbose",
            "System": "Information",
            "Microsoft": "Information"
        }
    },
    "GoogleAnalytics": {
        "Account": [
            {
                "Name": "AccountName",
                "ServiceAccountEmailAddress": "[email protected]",
                "KeyFileName": "key1.p12",
                "Password": "notasecret"

            },
            {
                "Name": "AnotherAccount",
                "ServiceAccountEmailAddress": "[email protected]",
                "KeyFileName": "key2.p12",
                "Password": "notasecret"

            }
        ],
        "KeyFilePath": "/googleApis/"
    }
}

The 'GoogleAnalytics' key contains an array of accounts that I wish to be able to access in a collection either as a list or an array. I created a POCO to represent this key that contains a corresponding collection of 'Account' objects:

public class GoogleAnalytics
{
    public Account[] Account { get; set; } = new Account[1];
    public string KeyFilePath { get; set; }

    public GoogleAnalytics()
    {

    }
}

And the 'Account' object:

public class Account
{
    private const string _applicationName = @"Storefront Analytics";
    private X509Certificate2 _certificate;
    private ServiceAccountCredential _credential;
    private AnalyticsService _service;

    #region |--Properties--|

    public string Name { get; set; }
    public string Password { get; set; }
    public string ServiceAccountEmailAddress { get; set; }
    public string KeyFileName { get; set; }
    public string KeyFilePath { get; set; }

    public string KeyFileFullPath
    {
        get
        {
            return $"{KeyFilePath}{KeyFileName}";
        }
    }

    public X509Certificate2 Certificate
    {
        get
        {
            if(_certificate == null)
            {
                ConfigureInstance();
            }

            return _certificate;
        }
        set
        {
            _certificate = value;
        }
    }

    public ServiceAccountCredential Credential
    {
        get
        {
            if (_credential == null)
            {
                ConfigureInstance();
            }

            return _credential;
        }
        set
        {
            _credential = value;
        }
    }

    public AnalyticsService Service
    {
        get
        {
            if (_service == null)
            {
                ConfigureInstance();
            }

            return _service;
        }
        set
        {
            _service = value;
        }
    }

    #endregion

    #region |--Constructors--|

    public Account()
    {

    }

    public Account(string password, string keyFileName, 
       string keyFilePath, 
       string serviceAccountEmailAddress, string accountName)
    {
        //TODO: Validate parameters

        Password = password;
        KeyFileName = keyFileName;
        KeyFilePath = keyFilePath;
        ServiceAccountEmailAddress = serviceAccountEmailAddress;
        Name = accountName;
    }

    #endregion

    private void ConfigureInstance()
    {
        Certificate = new X509Certificate2(KeyFileFullPath, Password, X509KeyStorageFlags.Exportable);

        Credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(ServiceAccountEmailAddress)
        {
            Scopes = new[] { AnalyticsService.Scope.Analytics }
        });

        Service = new AnalyticsService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = Credential,
            ApplicationName = _applicationName
        });
    }
}

My Controller:

public class GoogleAnalyticsController : Controller
{
    #region |--Properties--|

    [FromServices]
    private IGoogleAnalyticsRepository _repo { get; set; }

    #endregion

    public GoogleAnalyticsController(IOptions<GoogleAnalytics> options)
    {
        var temp = options.Value;
    }
}

The 'KeyFilePath' property is properly set in the IOptions instance. enter image description here

The problem I am having is that the Account array contains null references - none of the accounts are being instantiated. I wondering if I am doing this wrong, or the Options Model doesn't support this type of behavior at this time?

Update in response to Shaun Luttin's answer

I implemented the changes listing in Shaun Luttin's answer. There seems to have been an additional problem. For whatever reason, all of the Account instances' properties were null until I simplified the class as follows:

public class Account
{

    public string Name { get; set; }
    public string Password { get; set; }
    public string ServiceAccountEmailAddress { get; set; }
    public string KeyFileName { get; set; }
    public string KeyFilePath { get; set; }

}
like image 614
AperioOculus Avatar asked Feb 18 '16 15:02

AperioOculus


People also ask

What is appsettings JSON in ASP NET Core?

The appsettings.json file is an application configuration file used to store configuration settings such as database connections strings, any application scope global variables, etc. If you open the ASP.NET Core appsettings.json file, then you see the following code by default which is created by visual studio.

How to map configuration to a poco object?

We can Map configuration to a POCO object by loading the configuration details into strongly typed global classes or can load into related classes using IOptions. Below is the equivalent Configuration model created representing the above apsettings.json.

How to read values from appsettings in ASP NET Core?

If you’re not working in ASP.NET Core, then you have to do a little bit more work to be able to read values from appsettings.json. Basically you have to add the appsettings.json file, add the configuration extension packages, initialize the configuration object, then read your custom values from the config. There’s nothing special about this file.

What is application settings in ASP core?

Application Settings (appsettings.json) in ASP.NET Core. appsettings.json is one of the several ways, in which we can provide the configuration values to ASP.NET core application. You will find this file in the root folder of our project.


Video Answer


1 Answers

Short Answer

I wondering if I am doing this wrong, or the Options Model doesn't support this type of behavior at this time?

You are doing one thing wrong. The Options Model does support arrays. You need NOT to initialize your array property with an array of size [1].

public Account[] Account { get; set; } = new Account[1];     // wrong
public Account[] Account { get; set; }                       // right

Demo

Here is a sample, just for you, that you can find here on GitHub.

MyOptions.cs

namespace OptionsExample
{
    public class MyObj
    {
        public string Name { get; set; }
    }

    public class MyOptions
    {
        public string Option1 { get; set; }

        public string[] Option2 { get; set; }

        public MyObj[] MyObj { get; set; }
    }
}

Startup.cs

namespace OptionsExample
{
    using Microsoft.AspNet.Builder;
    using Microsoft.AspNet.Hosting;
    using Microsoft.AspNet.Http;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.OptionsModel;
    using System.Linq;

    public class Startup
    {
        public IConfigurationRoot Config { get; set; }
        public Startup(IHostingEnvironment env)
        {
            Config = new ConfigurationBuilder().AddJsonFile("myoptions.json").Build();
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions();
            services.Configure<MyOptions>(Config);
        }

        public void Configure(IApplicationBuilder app, 
            IOptions<MyOptions> opts)
        {
            app.Run(async (context) =>
            {
                var message = string.Join(",", opts.Value.MyObj.Select(a => a.Name));
                await context.Response.WriteAsync(message);
            });
        }
    }
}

myoptions.json

{
    "option1": "option1val",
    "option2": [
        "option2val1",
        "option2val2",
        "option2val3"
    ],
    "MyObj": [
        {
            "Name": "MyObj1"
        },
        {
            "Name": "MyObj2"
        }
    ]
}

project.json dependencies

"dependencies": {
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final"
}

Output

All options are present.

like image 116
Shaun Luttin Avatar answered Oct 07 '22 12:10

Shaun Luttin