读取配置项并使用 `IOptions<T>` 失败

Reading config item and using `IOptions<T>` failing

我不明白!我发誓我会严格按照文档 (Options pattern in ASP.NET Core) 进行操作,但是一旦我开始使用我的服务,选项值为 null。

这是 appsettings.json 文件内容;

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConfigStrings": {
    "IDProofingQuestionsPath": "C:\dev\...\wwwroot\sample-data\idProofingQuestionsMOCK.json"
  }
}

(如你所知,此路径用于测试某些内容,不会永久存在。)

这是我的 ConfigureServices() 方法。

public void ConfigureServices(IServiceCollection services)
{
    // IDProofingQuestionsPathOptions.IDProofingQuestionsPath <- Section:Option string for the Settings file.
    services.Configure<IDProofingQuestionsPathOptions>(Configuration.GetSection(IDProofingQuestionsPathOptions.IDProofingQuestionsPath));

    // This is the service into which I'm trying to inject this 'Option'
    services.AddScoped<IIDProofingServices, IDProofingServices>();

    services.AddDistributedMemoryCache();

    services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromSeconds(10);
        options.Cookie.HttpOnly = true;
        options.Cookie.IsEssential = true;
    });

    services.AddControllersWithViews();
}

这是我的服务代码,我试图将 IDProofingQuestionsPathOptions 实例注入其中。

public class IDProofingServices : IIDProofingServices
{
    private readonly string _proofingQuestionsPath;

    /// <summary>
    /// This is a parameterized constructor for allowing Dependency Injection
    /// </summary>
    public IDProofingServices(
        IOptions<IDProofingQuestionsPathOptions> proofingQuestionsPath)
    {
        if (proofingQuestionsPath == null)
        {
            throw new ArgumentNullException(nameof(proofingQuestionsPath));
        }

        if (string.IsNullOrWhiteSpace(proofingQuestionsPath.Value.IdProofingQuestionsPath))
        {
            // my code ends up here, and I just do NOT get what I'm doing wrong.
            throw new ArgumentNullException("proofingQuestionsPath.Value.IdProofingQuestionsPath");
        }

        _proofingQuestionsPath = proofingQuestionsPath.Value.IdProofingQuestionsPath;
    }

    ...
    

哦,当然还有选项对象。

public class IDProofingQuestionsPathOptions
{
    public const string IDProofingQuestionsPath = "ConfigStrings:IDProofingQuestionsPath";

    public string IdProofingQuestionsPath { get; set; }
}

Configure method expects a configuration section object, but your call to GetSection 仅提供 string 值,没有任何可以绑定到选项对象的子项。

一个简单的修复方法是直接绑定到 ConfigStrings 属性,或者为您的路径 属性.

引入一个 JSON 包装器

后一种解决方案的最小化示例:

启动:

public void ConfigureServices(IServiceCollection services)
{
    // Bind to the 'MyPathOptions' wrapper object
    services.Configure<PathOptions>(Configuration.GetSection("ConfigStrings:MyPathOptions"));

    // ...
}

路径选项:

public class PathOptions
{
    public string MyPath { get; set; }
}

appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConfigStrings": {
    "MyPathOptions": {
      "MyPath": "abc"
    }
  }
}

测试控制器:

[Route("")]
public class TestController : Controller
{
    private readonly IOptions<PathOptions> _pathOptions;

    public TestController(IOptions<PathOptions> pathOptions)
    {
        _pathOptions = pathOptions ?? throw new ArgumentNullException(nameof(pathOptions));
    }

    [HttpGet]
    public IActionResult Index()
    {
        return Ok(_pathOptions);
    }
}