configuration.getValue或configuration.getsection始终返回null

时间:2018-12-29 16:46:22

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

我是.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");

以上两行都为GetSectionGetValue返回空值

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

6 个答案:

答案 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值绑定到EmailSettingsStartup.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();
        }
    }

控制器类

enter image description here

您需要使用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对象。