configuration.getValue 或 configuration.getsection 总是返回 null

Posted

技术标签:

【中文标题】configuration.getValue 或 configuration.getsection 总是返回 null【英文标题】:configuration.getValue or configuration.getsection always returns null 【发布时间】:2019-05-27 00:58:31 【问题描述】:

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

【问题讨论】:

你通常在Startup.cs中初始化IConfiguration;不在Program.cs。如果您按照您描述的方式获得 null,则说明那里有问题。请显示Startup.cs docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/… 我正在关注这个。我也尝试了 Options Pattern,但是没有用... .Net Core 2.2 并暂时使用 IIS Express.. 【参考方案1】:

在 Controller 中访问配置与在 Startup.cs 中的工作方式略有不同。我之前做过这个,只需按照以下步骤操作:

Nuget:Microsoft.Extensions.Configuration.Binder

将您想要访问的所有配置放在控制器中的一个部分中,例如“电子邮件设置”:

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; 

然后将您的配置值绑定到Startup.cs 中的EmailSettings 类的实例,并将该对象添加到依赖注入容器:

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 文件的值。你应该可以复制和粘贴这个!玩得开心! :)

【讨论】:

不,这两行代码表明GetSectionGetValue 都没有返回任何值。 更新为在控制器中工作。我自己测试过,试试看:)【参考方案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 的调用,这样基本路径就不会被覆盖。我知道你已经发现了这一点,但我想确保你对这里出了什么问题有一个解释。

【讨论】:

在将其部署到 1) 旧版本的 IIS 或 2) 最新版本的 IIS 时是否有任何影响?如果我们为我们的项目设置了“进程中”,我们是否永远不会使用 config.SetBasePath,即使它在创建时就在项目中?如果是这样,我猜它只是 MS 没有更新它的模板。【参考方案3】:

您犯了一个简单的错误,忘记在“EmailSettings”中添加“Email”。如下所示更新您的 json 并使用config.GetSection("EmailSettings")["Email"]; 获取电子邮件

"EmailSettings": 
    "EmailTemplatesPath": "EmailTemplates",
    "Email": "aa@aa.com"
  ,

希望这能解决您的问题。

编辑:

如果您想从 appsettings 中获取这些值,而不是启动,您应该将这些配置值加载到设置类中,然后将适当的 IOptions 实例注入您要在其中使用这些设置的方法构造函数。为此,请看我的回答here。

【讨论】:

这是两个独立的语句,表明它们都没有返回任何值。 您能否在此链接上看到我的答案,并通过设置类从 appsetting.json 获取这些值,然后使用 IOptions 将其注入控制器。 ***.com/a/53904527/5198054【参考方案4】:

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"
        

【讨论】:

这个config["EmailSettings:EmailTemplatesPath"] 仍然返回null 并据此docs.microsoft.com/en-us/dotnet/api/…绑定在.Net Core 2.2中不可用 请尝试用一个控制器创建简单的MVC项目来读取配置文件。我已经更新了答案并在其中添加了代码示例。尽量保持这个虚拟项目非常简单,不要在管道中添加任何中间件,除了 MVC。 谢谢。这有帮助。我创建了一个空应用程序,它正确返回了配置值。然后我比较了这两个program.cs,问题出在这一行我不得不 .ConfigureAppConfiguration((hostingContext, config.SetBasePath(Directory.GetCurrentDirectory()); ) 不知道为什么会这样。 MSDN 说我需要添加... docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/…【参考方案5】:

虽然其他人已经解决了这个问题,但如果您想保持启动服务代码不变,只需将您的 Web API 控制器更改为以下内容:

private readonly EmailSettings _emailSettings;

public EmailController(IOptions<EmailSettings> emailSettings)

    _emailSettings = emailSettings.Value;

重点是.Value。这就是您的代码返回 null 的原因。我还建议将 program.cs 更改回默认值。要在操作方法中使用它,只需执行以下操作:

_email.settings.EmailTemplatesPath

最后一件事 - 确保您的 EmailSettings 类结构与您的 json 完全相同。

【讨论】:

【参考方案6】:

你可以这样做

services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
services.AddTransient(p => p.GetRequiredService<IOptions<EmailSettings>>().Value);

并通过构造函数 DI 初始化 EmailSettings 对象。

【讨论】:

以上是关于configuration.getValue 或 configuration.getsection 总是返回 null的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET CORE 中不允许主域的 CORS 问题

PHP MySql MsSql 如何插入或更新 ['] 或 ["] 或 [`] 字符?

与、或、异或运算

jQuery 或原始 JavaScript 是不是预编译或缓存变量表达式或选择器?

QGraphicsView 或 QWidget 完成绘制或渲染时是不是存在信号或事件?

KendoGrid 禁用或启用(编辑、添加或删除按钮)基础(true 或 false 中)