在 .NET Core 中从 appsettings.json 获取值
在 .NET Core 中从 appsettings.json 获取值
不确定我在这里漏掉了什么,但我无法在我的.Net Core应用程序中获取我的appsettings.json中的值。我有我的appsettings.json如下:
{ "AppSettings": { "Version": "One" } }
启动:
public class Startup { private IConfigurationRoot _configuration; public Startup(IHostingEnvironment env) { _configuration = new ConfigurationBuilder() } public void ConfigureServices(IServiceCollection services) { //Here I setup to read appsettings services.Configure(_configuration.GetSection("AppSettings")); } }
模型:
public class AppSettings { public string Version{ get; set; } }
控制器:
public class HomeController : Controller { private readonly AppSettings _mySettings; public HomeController(IOptions settings) { //This is always null _mySettings = settings.Value; } }
_mySettings
始终为空。我是否漏掉了些什么?
只需要创建一个任意名称的.cs文件,并粘贴以下代码.
using System; using System.IO; using Microsoft.Extensions.Configuration; namespace Custom { static class ConfigurationManager { public static IConfiguration AppSetting { get; } static ConfigurationManager() { AppSetting = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("YouAppSettingFile.json") .Build(); } } }
必须将YouAppSettingFile.json文件名替换为您的文件名.
您的.json文件应如下所示.
{ "GrandParent_Key" : { "Parent_Key" : { "Child_Key" : "value1" } }, "Parent_Key" : { "Child_Key" : "value2" }, "Child_Key" : "value3" }
现在您可以使用它。
不要忘记在要使用的类中添加引用.
using Custom;
检索值的代码.
string value1 = ConfigurationManager.AppSetting["GrandParent_Key:Parent_Key:Child_Key"]; string value2 = ConfigurationManager.AppSetting["Parent_Key:Child_Key"]; string value3 = ConfigurationManager.AppSetting["Child_Key"];
程序和启动类
ASP.NET Core 6.x
ASP.NET Core 6.x 在 Program
类中带来了另一个重大变化:
- 如果选择使用顶层语句,就不需要
Program.Main()
样板代码 - 隐式使用指令
- 所有内容都在
Program
文件中,不需要Startup
类 - 引入了
WebApplication
和WebApplicationBuilder
有人说这些变化对新手学习 ASP.NET Core 很有帮助,但我有点不这么认为。我觉得 Program
和 Startup
的分离更有意义,至少对我来说是这样。
总之……
下面是 Program.cs
的外观:
// Program.cs public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); var app = builder.Build(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/errors"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllerRoute( name: "areaRoute", pattern: "{area:exists}/{controller=home}/{action=index}/{id?}"); app.MapControllerRoute( name: "default", pattern: "{controller=home}/{action=index}/{id?}"); app.Run(); } }
你可以大致看出 WebApplication.CreateBuilder()
和 builder.Build()
之间的部分是旧的 ConfigureServices(IServiceCollection services)
的作用。而在 app.Run()
之前的部分则是旧的 Startup
的 Configure()
做的事情。
最重要的是,IConfiguration
被注入到管道中,所以你可以在控制器中使用它。
ASP.NET Core 3.x 到 5
ASP.NET Core 3.x 带来了一些变化,试图支持其他方法,比如各种服务,所以将 web 主机替换为更通用的主机构建器:
// Program.cs public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }; } }
虽然如此,Startup
类看起来与 2.x 版本非常相似。
ASP.NET Core 2.x
你不需要在 Startup
构造函数中新建 IConfiguration
。它的实现将由 DI 系统注入。
// Program.cs public class Program { public static void Main(string[] args) { BuildWebHost(args).Run(); } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup() .Build(); } // Startup.cs public class Startup { public IHostingEnvironment HostingEnvironment { get; private set; } public IConfiguration Configuration { get; private set; } public Startup(IConfiguration configuration, IHostingEnvironment env) { this.HostingEnvironment = env; this.Configuration = configuration; } }
ASP.NET Core 1.x
你需要告诉 Startup
加载 appsettings 文件。
// Program.cs public class Program { public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup() .UseApplicationInsights() .Build(); host.Run(); } } //Startup.cs public class Startup { public IConfigurationRoot Configuration { get; private set; } public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); this.Configuration = builder.Build(); } ... }
获取值
有很多方法可以从应用程序设置中获取你配置的值:
- 使用
ConfigurationBuilder.GetValue
的简单方法 - 使用选项模式
假设你的 appsettings.json
如下:
{ "ConnectionStrings": { ... }, "AppIdentitySettings": { "User": { "RequireUniqueEmail": true }, "Password": { "RequiredLength": 6, "RequireLowercase": true, "RequireUppercase": true, "RequireDigit": true, "RequireNonAlphanumeric": true }, "Lockout": { "AllowedForNewUsers": true, "DefaultLockoutTimeSpanInMins": 30, "MaxFailedAccessAttempts": 5 } }, "Recaptcha": { ... }, ... }
简单方法
你可以将整个配置注入到你的控制器/类的构造函数中(通过 IConfiguration
),并使用指定的键获取你想要的值:
public class AccountController : Controller { private readonly IConfiguration _config; public AccountController(IConfiguration config) { _config = config; } [AllowAnonymous] public IActionResult ResetPassword(int userId, string code) { var vm = new ResetPasswordViewModel { PasswordRequiredLength = _config.GetValue( "AppIdentitySettings:Password:RequiredLength"), RequireUppercase = _config.GetValue ( "AppIdentitySettings:Password:RequireUppercase") }; return View(vm); } }
选项模式
ConfigurationBuilder.GetValue
的作用是从应用程序设置中获取一个或两个值非常好。但如果要从应用程序设置中获取多个值,或者不想在多个地方硬编码这些键字符串,那么使用选项模式可能更容易。选项模式使用类来表示层次结构 / 结构。
要使用选项模式:
- 定义类以表示结构
- 注册这些类所绑定的配置实例
- 将
IOptions
注入到您想获取值的控制器/类构造函数中
1. 定义配置类以表示结构
您可以定义具有属性的类,这些属性需要完全匹配应用程序设置中的键。类名不必与应用程序设置中的部分名称匹配:
public class AppIdentitySettings { public UserSettings User { get; set; } public PasswordSettings Password { get; set; } public LockoutSettings Lockout { get; set; } } public class UserSettings { public bool RequireUniqueEmail { get; set; } } public class PasswordSettings { public int RequiredLength { get; set; } public bool RequireLowercase { get; set; } public bool RequireUppercase { get; set; } public bool RequireDigit { get; set; } public bool RequireNonAlphanumeric { get; set; } } public class LockoutSettings { public bool AllowedForNewUsers { get; set; } public int DefaultLockoutTimeSpanInMins { get; set; } public int MaxFailedAccessAttempts { get; set; } }
2. 注册配置实例
然后您需要在启动时的ConfigureServices()
中注册此配置实例:
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; ... namespace DL.SO.UI.Web { public class Startup { ... public void ConfigureServices(IServiceCollection services) { ... var identitySettingsSection = _configuration.GetSection("AppIdentitySettings"); services.Configure(identitySettingsSection); ... } ... } }
对于 ASP.NET Core 6.x
由于我在 ASP.NET Core 6.x 开头提到的更改,您需要绑定部分并将其添加到 DI 中,如下所示:
// Program.cs public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); builder.Services.Configure( builder.Configuration.GetSection("AppIdentitySettings") ); var app = builder.Build(); ... app.Run(); } }
您可以在此处阅读更多有关此话题的信息。
3. 注入 IOptions
最后,在您想获取值的控制器/类上,您需要通过构造函数注入IOptions
:
public class AccountController : Controller { private readonly AppIdentitySettings _appIdentitySettings; public AccountController(IOptionsappIdentitySettingsAccessor) { _appIdentitySettings = appIdentitySettingsAccessor.Value; } [AllowAnonymous] public IActionResult ResetPassword(int userId, string code) { var vm = new ResetPasswordViewModel { PasswordRequiredLength = _appIdentitySettings.Password.RequiredLength, RequireUppercase = _appIdentitySettings.Password.RequireUppercase }; return View(vm); } }