asp5 IConfigurationRoot获取json数组

时间:2015-12-04 07:18:09

标签: c# asp.net json asp.net-mvc asp.net-core

我正在尝试向我的asp 5 mvc 6 web应用程序(“rc1-final”库)提供一些额外的配置数据,以便部署在Azure上。此附加数据的一部分由json文件中的数据数组组成。我可以将这个json文件添加到我的配置中,并且在调试时如果我观察配置对象,我可以浏览到提供者条目,看到它确实联系了我正在寻找的数据数组。

但是,尝试Configuration["extraData"]会产生null(因为该属性的“值”为null,即使它显然包含元素数组。

访问存储在json配置中的单个值(例如我的数据库连接字符串和其他值)没有问题。看起来好像不支持数组格式的json数据?

请参阅以下示例json文件(根据jsonlint进行验证,对我来说似乎很好)...

//extraData.json
{
  "ExtraData": [
    {
      "Id": 1,
      "Description": "The first identifier"
    },
    {
      "Id": 2,
      "Description": "The second identifier"
    },
    {
      "Id": 3,
      "Description": "The third identifier"
    }
  ]
}

...以及以下示例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; }
    }
}

我不得不做的事情(这看起来很神圣,特别是考虑到现在可用的配置系统)......

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);

我也不确定azure的支持就像这样做文件io。

我发现这个资源表明支持array / IEnum,但它只是使用内存提供程序...
http://github.com/aspnet/Configuration/blob/dev/test/Microsoft.Extensions.Configuration.Binder.Test/ConfigurationCollectionBindingTests.cs

此资源是来自MS的文档...
http://docs.asp.net/en/latest/fundamentals/configuration.html

自发布以来搜索时出现的一些相关问题(不是1:1与我的问题有关,但可能对其他搜索有用) 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

4 个答案:

答案 0 :(得分:19)

我们现在可以使用GetSectionGetChildren以及一些LINQ。

// appsettings.json
{
    "SomeArray": [
        "Foo", 
        "Bar",
        "Baz"
    ]
}

// Startup.cs
var someArray = configuration
    .GetSection("SomeArray")
    .GetChildren()
    .Select(x => x.Value)
    .ToArray();

Configuration repository's ArrayTest还有一个演示。

答案 1 :(得分:9)

试试这个:

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; }
    }
}

修改

如果编译器抱怨services.Configure<List<ExtraData>>(Configuration.GetSection("ExtraData")),请添加一个NuGet引用Microsoft.Extensions.Options.ConfigurationExtensions

您也可以将它注入构造函数:

// using Microsoft.Extensions.Options;
public class HomeController : Controller
{
    private List<ExtraData> _extraData;
    public HomeController(IOptions<List<ExtraData>> extraData)
    {
        _extraData = extraData.Value;
    }
}

答案 2 :(得分:5)

您可以通过以下方式检索设置:

var extraDataSection = configuration.GetSection("ExtraData");
foreach (IConfigurationSection section in extraDataSection.GetChildren())
{
    var id = section.GetValue<int>("Id");
    var description = section.GetValue<string>("Description");
}

答案 3 :(得分:1)

使用最新版本,我无需任何额外的NuGet包即可解决此问题:

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";
}