我是.Net Core的新手,正在尝试从appsettings.json
文件中获取值,但是我错过了一些非常基本的知识。请让我知道我做错了什么...
这是代码...
Program.cs
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory());
})
Startup.cs
public IConfiguration Configuration { get; private set; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
}
Web API控制器
private readonly IConfiguration config;
public EmailController(IConfiguration configuration)
{
if (configuration != null)
{
config = configuration;
}
}
操作方法
var emailTemplatesRelativePath = config.GetSection("EmailSettings");
var email = config.GetValue<string>("Email");
以上两行都为GetSection
和GetValue
返回空值
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Information"
}
},
"ConnectionStrings": {
"FCRContext": "server=xxx;database=xxx;user id=xxx;password=xxx"
},
"AllowedHosts": "*",
"EmailSettings": {
"EmailTemplatesPath": "EmailTemplates"
},
"Email": "aa@aa.com"
}
答案 0 :(得分:2)
您犯了一个简单的错误,忘记将“电子邮件”添加到“电子邮件设置”中。如下所示更新您的json并使用config.GetSection("EmailSettings")["Email"];
"EmailSettings": {
"EmailTemplatesPath": "EmailTemplates",
"Email": "aa@aa.com"
},
希望这可以解决您的问题。
编辑:
如果要从应用程序设置中获取这些值,而不是启动时,则应将这些配置值加载到设置类中,然后将适当的IOptions实例注入到要使用这些设置的方法构造函数中。为此,请参阅我的答案here。
答案 1 :(得分:2)
在IIS(或IIS Express)中托管in-process时,Directory.GetCurrentDirectory()
将返回与运行out-of-process时返回的路径不同的路径。在ASP.NET Core 2.1之前,基于IIS的托管始终处于进程外,但是ASP.NET Core 2.2引入了在进程内运行的能力(这是创建新项目时的默认设置)。
在进程外运行时,Directory.GetCurrentDirectory()
会将路径返回到ASP.NET Core应用程序本身,而在进程内运行时,它将返回路径到IIS(或IIS Express,例如“ C:\ Program Files \ IIS Express“)。
根据您的问题,相关代码如下:
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory());
})
在这里,在致电SetBasePath
之前,已经将IConfigurationBuilder
设置为使用正确的路径。您的通话本身将覆盖此路径,例如将其设置为“ C:\ Program Files \ IIS Express”。使用此覆盖的基本路径,您的appsettings.json
等文件不再存在,因为它们不存在于例如“ C:\ Program Files \ IIS Express”,因此这些文件不会加载任何配置。
解决方案是简单地删除对ConfigureAppConfiguration
的调用,以使基本路径不会被覆盖。我知道您已经发现了这个问题,但是我想确保您对这里的问题有一个解释。
答案 2 :(得分:1)
在Controller中访问配置的方式与在Startup.cs中访问方式略有不同。我刚才做了这个,只需按照以下步骤操作即可:
将要在控制器中访问的所有配置都放在一个部分中,例如“电子邮件设置”:
appsettings.json
{
"EmailSettings": {
"EmailTemplatesPath": "EmailTemplates",
"Email": "aa@aa.com"
}
}
然后在您的Web API项目中创建一个名为EmailSettings.cs
的类:
EmailSettings.cs
public class EmailSettings
{
public string EmailTemplatesPath { get; set; }
public string Email { get; set; }
}
然后将您的Config值绑定到EmailSettings
中Startup.cs
类的实例,并将该对象添加到依赖注入容器中:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
EmailSettings emailSettings = new EmailSettings();
Configuration.GetSection("EmailSettings").Bind(emailSettings);
services.AddSingleton(emailSettings);
}
现在,您可以像这样简单地将其添加到构造函数中,从而在Api控制器中请求配置:
Web API控制器
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
EmailSettings _emailSettings;
public ValuesController(EmailSettings emailSettings)
{
_emailSettings = emailSettings;
}
....
}
只需在我当前的项目(.NET Core 2.2 Web Api)中再次尝试此操作即可。我在ValuesController构造函数中放置了一个断点,并且_emailSettings对象包含了appsettings.json
文件中的值。您应该可以复制并粘贴!玩得开心! :)
答案 3 :(得分:0)
Program.cs
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
Startup.cs:
public partial class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.UseMvcWithDefaultRoute();
}
}
控制器类
您需要使用Bind()方法从section中获取值。
EmailSetting option = new EmailSetting();
//You need to bind the section with data model,
//it will automatically map config key to property of model having same name
config.GetSection("EmailSettings").Bind(option);
//Alternative to this you can read nested key using below syntax
var emailTemplatesPath = config["EmailSettings:EmailTemplatesPath"];
var emailInEmailSettings = config["EmailSettings:Email"];
// If email key is not nested then you can access it as below
var email = config.GetValue<string>("EmailOutside");
电子邮件设置模型:-(属性名称应与配置密钥匹配)
public class EmailSetting
{
public string EmailTemplatesPath { get; set; }
public string Email { get; set; }
}
Appsetting.json:-
{
"AllowedHosts": "*",
"EmailSettings": {
"EmailTemplatesPath": "EmailTemplates",
"Email": "aa@aa.com"
},
"EmailOutside": "aa@aa.com"
}
答案 4 :(得分:0)
虽然其他人已经解决了这个问题,但是如果您想保留启动服务代码,只需将Web API控制器更改为以下内容即可:
private readonly EmailSettings _emailSettings;
public EmailController(IOptions<EmailSettings> emailSettings)
{
_emailSettings = emailSettings.Value;
}
重点是。值。这就是为什么您的代码返回null的原因。我还建议将program.cs更改回默认值。并将其用于操作方法中,只需执行以下操作:
_email.settings.EmailTemplatesPath
最后一件事-确保您的EmailSettings类结构与json完全相同。
答案 5 :(得分:0)
您可以执行以下操作
services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
services.AddTransient(p => p.GetRequiredService<IOptions<EmailSettings>>().Value);
并通过构造函数DI初始化EmailSettings对象。