【问题标题】:ASP.NET Core Configuration Section in Startup启动中的 ASP.NET Core 配置部分
【发布时间】:2017-03-16 19:26:53
【问题描述】:

我正在将一个 ASP.NET 5 RC1 项目迁移到 ASP.NET Core,并且遇到了一个我尚未看到或找到解决方案的有趣问题。

为了在 Startup 中使用配置设置,我之前通过以下方式检索了配置

// Works fine for DI both in ASP.NET 5 RC1 and ASP.NET Core
services.Configure<SomeConfigurationClass>(Configuration.GetSection("SomeConfigurationSection"));

// How I previous retrieved the configuration for use in startup. 
// No longer available in ASP.NET Core
var someConfigurationToUseLater = Configuration.Get<SomeConfigurationClass>("SomeConfigurationSection");

更新到 ASP.NET Core 1.0 后,似乎 Configuration.Get() 不再可用。

我已尝试更新代码以使用 Configuration.GetValue() 但这似乎不适用于对象,并且仅在提供值的路径时才有效。这为我的大多数配置类留下了一个解决方法

var someConfigurationName = "someConfiguration";    
var someConfigurationClass = new SomeConfigurationClass()
{
    Value1 = Configuration.GetValue<string>($"{someConfigurationName}:value1"),
    Foo = Configuration.GetValue<string>($"{someConfigurationName}:foo"),
    Bar = Configuration.GetValue<string>($"{someConfigurationName}:bar")
};

但是,当配置类包含对象数组时,这是一个问题。在我的例子中,一组 Client 对象

public class ClientConfiguration
{
    public Client[] Clients { get; set; }
}

使用以下配置

"configuredClients": {
  "clients": [
    {
      "clientName": "Client1",
      "clientId": "Client1"
    },
    {
      "clientName": "Client2",
      "clientId": "Client2"
    }
  ]
}

以前这会绑定到我的配置类的 Clients 属性没有问题,但我在 ASP.NET Core 1.0 中找不到这样做的方法

【问题讨论】:

    标签: c# asp.net-core asp.net-core-1.0


    【解决方案1】:

    使用 ASP.NET Core 2.0(基本上是 Core 1.1+),IConfiguration 被注入到 Startup,并且可以在 ConfigureServices()Configure() 方法中使用。

    如接受的答案所示,配置可以绑定到对象。但如果只需要一个值,则基于键的方法效果很好。

    IConfiguration 仍然可以使用冒号 : 分隔的字符串键。对于array,使用从 0 开始的索引。或者使用具有相同键的通用getValue&lt;T&gt;() 方法。请参见下面的示例:

    var clientId2 = Configuration["configuredClients:clients:1:clientId"]?.ToString();
    var clientName1 = Configuration.GetValue<string>("configuredClients:clients:0:clientName");
    

    在其他类(例如控制器)中使用相同的配置值

    1. 注入IConfiguration 并使用与上述相同的基于密钥的方法。或者
    2. 向 DI 容器注册强类型配置对象的实例,并将该对象直接注入客户端类。

    示例代码如下:

    //In Startup.ConfigureServices()
    var clientConfig = Configuration.GetSection("configuredClients")
        .Get<ClientConfiguration>();
    services.AddSingleton(clientConfig);
    
    //Controller
    public class TestController : Controller
    {
        IConfiguration _configStore;
        ClientConfiguration _clientConfiguration;
    
        public TestController(IConfiguration configuration, 
            ClientConfiguration clientConfiguration)
        {
            _configStore = configuration;
            _clientConfiguration = clientConfiguration;
        }
    
        public IActionResult Get()
        {
            //with IConfiguration
            var clientId1 = _configStore
                .GetValue<string>("configuredClients:clients:0:clientId");
    
            //with strongly typed ClientConfiguration
            var clientName1 = _clientConfiguration.Clients[0]?.ClientName;
    
            return new OkObjectResult("Configuration test");
        }
    }
    

    更多示例here

    【讨论】:

    • 对于您提出的方案,最好的解决方案是使用services.Configure&lt;ClientConfiguration&gt;(Configuration.GetSection("configuredClients")),而不是将IConfiguration 注入到您的控制器中注入IOptions&lt;ClientConfiguration&gt;
    • 在这里,我展示了注入IConfiguration 作为选项之一,我还展示了直接注入ClientConfiguration。 “最佳”解决方案取决于多种因素。使用IOptions&lt;&gt; 也是一个选项,IOptionsSnapshot 和其他选项也是如此。
    【解决方案2】:

    更新答案
    对于 ASP Core 1.1.0 通用模型绑定现在使用 Get 完成:

    var config = Configuration.GetSection("configuredClients").Get<ClientConfiguration>();
    

    原答案
    这个怎么样:

    var config = Configuration.GetSection("configuredClients").Bind<ClientConfiguration>();
    

    【讨论】:

    • 值得注意的是,我必须将 Microsoft.Extensions.Configuration 和 Microsoft.Extentions.Options.ConfigurationExtensions 更新为 1.1.0-preview1-final
    • 在 1.1 的最终版本中是否再次删除了这个?
    • 看起来它可能已重命名为 Get&lt;&gt;docs.microsoft.com/en-us/aspnet/core/fundamentals/…
    • 为了在 1.1 中工作,我必须从 NuGet 添加 Microsoft.Extensions.Configuration.Binder
    【解决方案3】:

    如果您想获得第一个“clientName”(预期为“Client1”),只需编写:

    Configuration.GetSection("configuredClients")["clients:0:clientName"];
    

    评论更新

    安装 .NET Core 1.0.1 并按照 @TomMakin 的方式进行。

    【讨论】:

    • 我想要完整的客户端列表,显然它是可配置的,有 x 个客户端需要稍后在配置设置中使用。所以不是一个真正可行的解决方案。
    • 安装 .NET Core 1.0.1 并采用@TomMakin 的方式。
    【解决方案4】:

    您通常不会自己在 ASP.NET Core 中手动读取配置,而是创建一个与您的定义匹配的对象。您可以在官方文档here 中阅读更多内容。

    例如

    public class MyOptions
    {
        public string Option1 { get; set; }
        public int Option2 { get; set; }
    }
    
    public void ConfigureServices(IServiceCollection services)
    {
        // Setup options with DI
        services.AddOptions();
        services.Configure<MyOptions>(Configuration);
    }
    

    然后,您只需将选项 IOptions&lt;MyOptions&gt; 注入您需要的地方。

    【讨论】:

    • 同样行不通,即使配置对象和json对象按照您建议的方式匹配,我仍然会得到null。稍后配置服务并注入 IOptions 似乎可以很好地检索配置值。问题是当我试图检索这些值以在 Startup 中使用时
    • 我不是 100% 确定你的意思,但是在 Configure 方法中使用 DI 容器对你有帮助吗?我认为可以在那里使用容器,但找不到如何做到这一点。
    • 这是一篇关于如何使用强类型配置节的好文章:How to use the IOptions pattern for configuration in ASP.NET Core RC2
    • 感谢您的帮助,但这不能解决我遇到的问题。将 Configuration 和 ConfigurationExtensions 包更新到 1.1.0-preview1-final 后,@Tom Makin 的解决方案非常完美。
    • 对不起,我帮不上忙,似乎我部分误解了你的问题:)
    猜你喜欢
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 2016-10-31
    • 1970-01-01
    相关资源
    最近更新 更多