I am trying to supply some additional configuration data to my asp 5 mvc 6 web app ("rc1-final" libraries) to be deployed on Azure. Part of this additional data consists of an array of data in a json file. I can add this json file to my configuration, and while debugging if I watch the configuration object I can browse to the provider entry and see it does in fact contact the array of data I'm looking for.
However, trying Configuration["extraData"]
yields null (as the "value" of that property is null, even though it clearly contains the array of elements.
I have no problem accessing single values that are stored in json config (such as my database connection string, and other values.) It just seems as though json data in array format is not supported?
See the following sample json file (which validates according to jsonlint and seems fine to me)...
//extraData.json
{
"ExtraData": [
{
"Id": 1,
"Description": "The first identifier"
},
{
"Id": 2,
"Description": "The second identifier"
},
{
"Id": 3,
"Description": "The third identifier"
}
]
}
...and the following sample Startup.cs...
//Startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Data.Entity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;
using System.IO;
using Microsoft.AspNet.Authentication.Cookies;
using System.Net;
namespace MyProj {
public class Startup {
public static IConfigurationRoot Configuration;
public Startup(IHostingEnvironment env) {
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile("extraData.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
MyDbSeed seed,
ILoggerFactory logging) {
dynamic xData = JObject.Parse("ExtraData"); //VALUE IS NULL, THROWS EX
var myList = JsonConvert
.DeserializeObject<List<MyID>>(
xData.ExtraData.ToString()
);
//Do something important with this list
}
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}
class MyID {
public int ID { get; set; }
public string Description { get; set; }
}
}
What I've been having to do instead (which seems hackish, especially given the handy Configuration system now available)...
dynamic xData = JObject.Parse(
File.OpenText(
env.MapPath(
@"..\extraData.json"
)
).ReadToEnd()
);
var xList = JsonConvert
.DeserializeObject<List<MyID>>(
xData.ExtraData.ToString()
);
//Do something important with the list, eg...
var o = new MyClass(xList);
I'm also uncertain as to the support on azure to do file io like this.
I found this resource which suggests that array/IEnum is supported, but it is just using an in-mem provider...
http://github.com/aspnet/Configuration/blob/dev/test/Microsoft.Extensions.Configuration.Binder.Test/ConfigurationCollectionBindingTests.cs
This resource is the documentation from MS...
http://docs.asp.net/en/latest/fundamentals/configuration.html
Some related questions that have turned up while searching since posted (not 1:1 related to my issue necessarily, but could prove useful for others searching)
How to use ConfigurationBinder in Configure method of startup.cs
Retrieve sections from config.json in ASP.NET 5
ASP.NET 5 (vNext) - Getting a Configuration Setting
We can now use GetSection
with GetChildren
and some LINQ.
// appsettings.json
{
"SomeArray": [
"Foo",
"Bar",
"Baz"
]
}
// Startup.cs
var someArray = configuration
.GetSection("SomeArray")
.GetChildren()
.Select(x => x.Value)
.ToArray();
There is also a demo in the Configuration repository's ArrayTest.
try this out:
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel;
using System.Collections.Generic;
namespace WebApplication1
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile("extraData.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.Configure<List<ExtraData>>(Configuration.GetSection("ExtraData"));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
List<ExtraData> result = app.ApplicationServices.GetRequiredService<IOptions<List<ExtraData>>>().Value;
// you should get what you need. It works in my computer with rc1 update 1
}
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}
public class ExtraData
{
public int Id { get; set; }
public string Description { get; set; }
}
}
EDIT
If compiler complains services.Configure<List<ExtraData>>(Configuration.GetSection("ExtraData"))
, please add a NuGet reference to Microsoft.Extensions.Options.ConfigurationExtensions
You may also inject it into constructor:
// using Microsoft.Extensions.Options;
public class HomeController : Controller
{
private List<ExtraData> _extraData;
public HomeController(IOptions<List<ExtraData>> extraData)
{
_extraData = extraData.Value;
}
}
You can retrieve settings this way:
var extraDataSection = configuration.GetSection("ExtraData");
foreach (IConfigurationSection section in extraDataSection.GetChildren())
{
var id = section.GetValue<int>("Id");
var description = section.GetValue<string>("Description");
}
With the latest versions I was able to solve this without any additional NuGet packages:
int extraDataCount = 0;
string id = Configuration[GetId(extraDataCount)];
string description = Configuration[GetDescription(extraDataCount)];
var extraDataList = new List<MyID>();
while(id != null && description != null)
{
extraDataList.Add(new MyID { ID = id, Description = description });
extraDataCount++;
id = Configuration[GetId(extraDataCount)];
description = Configuration[GetDescription(extraDataCount)];
}
private string GetId(int extraDataCount)
{
return "ExtraData:" + extraDataCount + ":Id";
}
private string GetDescription(int extraDataCount)
{
return "ExtraData:" + extraDataCount + ":Description";
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With