如何从ASP.NET Core中的.json文件读取AppSettings值

440

我已经按照以下方式在appsettings/Config.json文件中设置了我的AppSettings数据:

{
  "AppSettings": {
        "token": "1234"
    }
}

我在网上搜索了如何从 .json 文件中读取 AppSettings 值的方法,但是没有找到有用的信息。

我尝试过:

var configuration = new Configuration();
var appSettings = configuration.Get("AppSettings"); // null
var token = configuration.Get("token"); // null

我知道在 ASP.NET 4.0 中你可以这样做:

System.Configuration.ConfigurationManager.AppSettings["token"];

但是在ASP.NET Core中我该如何实现这个呢?


可能是重复的问题:ASP.NET 5(vNext)-获取配置设置 - mason
提供额外见解的MSDN参考资料:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration?tabs=basicconfiguration - MDMoore313
这可以通过在.NET Core 2.0中使用IConfiguration的依赖注入来简化。具体解释请参见http://www.coding-issues.com/2018/10/read-values-from-appsettings-json-.net-core.html。 - Ranadheer Reddy
6
依赖注入适用于控制器。但是如果有人需要在中间件中读取一个值,该怎么办? - Alexander Ryan Baggett
如果你正在寻找一个 .net core 6 控制台应用程序,你可以看一下这个链接:https://dev59.com/QFEG5IYBdhLWcg3wfviM#70242856 - VivekDev
29个回答

5

.NET Core 2.2 的方式

(毫无疑问,Microsoft 在下一个 .NET 版本中会再次将其更改为完全不同的东西。)

1. appSettings.json

它可能看起来像这样。在此处,我们将加载 Setting1 和 Setting2。

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Setting1": "abc",
  "Setting2": 123
}

2. AppSettings.cs

POCO类用于保存Setting1和Setting2。我们将把appsettings.json加载到这个类对象中。POCO类的结构应该与JSON文件匹配,如果需要,属性可以嵌套在其他属性/类中。

public class AppSettings
{
    public string Setting1 { get; set; }
    public int Setting2 { get; set; }
}

3 Startup.cs

在Startup.cs中加载appSettings.json,并且开始使用它:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        AppSettings settings = new AppSettings();

        Configuration = configuration;
        configuration.Bind(settings);

        // Now start using it
        string setting1 = settings.Setting1;
        int setting2 = settings.Setting2;
    }

1
使用 new ConfigurationBuilder()...Build()config.Bind(appSettings) 的组合对我很有帮助,谢谢。 - Pierre

4

通过调用Get<YourType>()在控制器中以对象的形式获取它:

public IActionResult Index([FromServices] IConfiguration config)
{
    BillModel model = config.GetSection("Yst.Requisites").Get<BillModel>();
    return View(model);
}

3

首先您需要注入IConfiguration,然后可以使用以下任一方法读取appsettings:

  1. Get a section data

    var redisConfig = configuration.GetSection("RedisConfig");
    
  2. Get a value within a section

    var redisServer = configuration.GetValue<string>("RedisConfig:ServerName");
    
  3. Get nested value within section

    var redisExpireMInutes = configuration.GetValue<int>("RedisConfig:ServerName:ExpireMInutes");
    

注入功能适用于控制器,但如果我想在中间件中使用它怎么办,比如这里?例如,我正在使用Redis作为中间件来缓存HTTP响应。 - Alexander Ryan Baggett

3

使用 .NET 7 并将所有内容放在 Program.cs

var token = builder.Configuration["AppSettings:token"]

2

这算是“作弊”吗?我只需在Startup类中将我的配置设置为静态,然后就可以从任何其他地方访问它:

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();

        Configuration = builder.Build();
    }

    public static IConfiguration Configuration { get; set; }

1
我知道这是老旧的,但人们仍在阅读它。这不是一个好习惯。这会创建对代码某一部分的直接引用,而不是使用DI来加载它,在创建代码映射时,将有太多地方指向代码,你将不得不进行重构。 - cpoDesign
为什么“直接引用我的代码”是不好的?DI 过度设计了一个简单的任务。 - Alex from Jitbit

0
您可以尝试下面的代码。这对我有效。
public class Settings
{
    private static IHttpContextAccessor _HttpContextAccessor;

    public Settings(IHttpContextAccessor httpContextAccessor)
    {
        _HttpContextAccessor = httpContextAccessor;
    }

    public static void Configure(IHttpContextAccessor httpContextAccessor)
    {
        _HttpContextAccessor = httpContextAccessor;
    }

    public static IConfigurationBuilder Getbuilder()
    {
        var builder = new ConfigurationBuilder()
          .SetBasePath(Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json");
        return builder;
    }

    public static string GetAppSetting(string key)
    {
        //return Convert.ToString(ConfigurationManager.AppSettings[key]);
        var builder = Getbuilder();
        var GetAppStringData = builder.Build().GetValue<string>("AppSettings:" + key);
        return GetAppStringData;
    }

    public static string GetConnectionString(string key="DefaultName")
    {
        var builder = Getbuilder();
        var ConnectionString = builder.Build().GetValue<string>("ConnectionStrings:"+key);
        return ConnectionString;
    }
}

在这里,我创建了一个类来获取连接字符串和应用程序设置。
在Startup.cs文件中,您需要按以下方式注册类。
public class Startup
{

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        var httpContextAccessor = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>();
        Settings.Configure(httpContextAccessor);
    }
}

0

除了 Ali的答案之外,您还需要在构造函数中注入IConfiguration对象:

appsettings.js

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "AppSettings": {
      "ServerUrl": "some url"
  }
  
}

定义 AppSettings 类。
    public class AppSettings
    {
        public string ServerUrl { get; set; }
    }

Startup.cs

 public class Startup
    {
        private readonly IConfiguration Configuration;
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            ...
        }
    }

控制器

    [Route("api/[controller]")]
    [ApiController]
    public class AuthenticationController : ControllerBase
    {
        private readonly AppSettings config;

        public AuthenticationController (IOptions<AppSettings> config)
        {
            this.config= config.Value;
        }

        [HttpGet("token")]

        public ActionResult Token()
        {
          var server=config.ServerUrl;

        }

适用于 .NET 5


0
在 .Net 6 中获取设置数据,我使用 IConfiguration 接口,并添加了一些抽象来帮助我在项目中进行测试,使我的代码更加灵活。
例如,在 appsettings.json 文件中有一些 API Url。
"ApiBaseUri": "https://dev.api.com/"

为了尽量减少由于下一个版本的.Net Core框架中与配置文件处理机制的变化而导致的代码更改成本,我使用了一个对接口进行封装的包装器。
public interface IConfigurationWrapper
{
    string? GetSectionValue(string key);
}

public class ConfigurationWrapper : IConfigurationWrapper
{
    private readonly IConfiguration _config;

    public ConfigurationWrapper(IConfiguration config)
    {
        _config = config;
    }

    public string? GetSectionValue(string key)
    {
        return _config.GetSection(key).Value;
    }
}

最后,还有一个特殊的界面来表示配置文件中的设置:
public interface IAppSettings
{
    Uri? GetApiBaseUri();
}

public class AppSettings : IAppSettings
{
    private const string ApiBaseUriSettingName = "ApiBaseUri";

    private readonly IConfigurationWrapper _config;

    public AppSettings(IConfigurationWrapper config)
    {
        _config = config;
    }

    public Uri? GetApiBaseUri()
    {
        string uriValue = _config.GetSectionValue(ApiBaseUriSettingName);

        return string.IsNullOrEmpty(uriValue) ? null : new Uri(uriValue);
    }
}

这就是我在代码中使用它的方式:
public class MyService : IMyService
{
    private readonly IAppSettings _settings;

    private readonly IRestRequestFactory _requestFactory;
    private readonly IRestResponseFactory _responseFactory;

    public MyService(IAppSettings settings, IRestRequestFactory requestFactory, IRestResponseFactory responseFactory)
    {
        _settings = settings;
        _requestFactory = requestFactory;
        _responseFactory = responseFactory;
    }

    public async Task<decimal?> GetSomeEndpointResponseAsync(FilterModel filter, CancellationToken token)
    {
        var request = _requestFactory.CreatePostRequest(ApiUrls.SomeEndpoint, filter);

        var response = await _responseFactory.GetRestResponseAsync<ResponseResultModel<decimal?>>(request, _settings.GetApiBaseUri(), token);

        return response.Data?.Data;
    }
}

而且我还可以轻松地用单元测试覆盖我的AppSettings
[TestFixture]
public class AppSettingsTests
{
    private Mock<IConfigurationWrapper> _configurationMock;

    private IAppSettings _settings;

    [SetUp]
    public void SetUp()
    {
        _configurationMock = new Mock<IConfigurationWrapper>();

        _settings = new AppSettings(_configurationMock.Object);
    }

    [Test]
    public void GetApiBaseUri_ApiBaseUriIsEmptyString_ReturnsNull()
    {
        // Arrange
        string uri = string.Empty;

        _configurationMock.Setup(m => m.GetSectionValue(It.IsAny<string>())).Returns(uri);

        // Act
        Uri? result = _settings.GetApiBaseUri();

        // Assert
        Assert.IsNull(result);
    }

    [Test]
    public void GetApiBaseUri_ApiBaseUriIsNull_ReturnsNull()
    {
        // Arrange
        string uri = null;

        _configurationMock.Setup(m => m.GetSectionValue(It.IsAny<string>())).Returns(uri);

        // Act
        Uri? result = _settings.GetApiBaseUri();

        // Assert
        Assert.IsNull(result);
    }
}

希望这能有所帮助。

-3

随着最新版本的netcoreapp 3.1发布,您可以轻松地完成此操作,无需任何第三方依赖。

创建了一个gist,但您可以使用此类来读取JSON文件并返回动态属性。

using System.Text.Json;
using System.IO;

class ConfigurationLoader
{

    private dynamic configJsonData;
    public ConfigurationLoader Load(string configFilePath = "appsettings.json")
    {
        var appSettings = File.ReadAllText(configFilePath);
        this.configJsonData = JsonSerializer.Deserialize(appSettings, typeof(object));
        return this;
    }

    public dynamic GetProperty(string key)
    {
        var properties = key.Split(".");
        dynamic property = this.configJsonData;
        foreach (var prop in properties)
        {
            property = property.GetProperty(prop);
        }

        return property;
    }
}

我特意为我的dotnet控制台应用程序创建了这个,以便我可以使用appconfig.json。我只需将以下代码放入我的Program.Main函数中:

var config = new ConfigurationLoader();
config.Load();
Console.WriteLine(config.GetProperty("Environment.Name"));

这将返回一个属性的 dynamic 对象。(如果不是原始类型,则为 JsonElement)。 我的 appsettings.json 文件如下:

{
  "Environment": {
    "Token": "abc-123",
    "Name": "Production"
  }
}

1
你不应该为已经内置在.NET Core中的功能编写自定义代码。这样做只会重复造轮子,而且还不如原来的好。 - Kellen Stuart
我很感激你的建设性批评,@kellen-stuart。当我遇到这个问题时,我无法找到.NET Core中用于加载控制台应用程序的appsettings的内置功能。你能指点我适当的资源,以便我可以更新我的解决方案吗? - Justin Gilman
1
使用 ConfigurationBuilder 是正确的方法;有一个名为 AddJsonFile 的方法 https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.configuration.configurationbuilder?view=dotnet-plat-ext-5.0 - Kellen Stuart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接