2

情况

我有 3 个 dotnet 核心项目有问题:

  • 网络 API
  • 工人服务
  • 类库

在类库中,我有一个共享的 EmailService 类,我在 Web API 和 Worker 服务中注册了依赖注入。

对于我的 sendgrid API 密钥,Web API 和 Worker Service 项目都具有相同的配置部分,并且它们使用 IOptions 模式以完全相同的方式绑定到 POCO。它们都使用该AddScoped方法注册。但是 EmailService 的实际类实现在共享类库中。在本地运行不会在类库(这可能是有道理的)以及 ETL 用户密码中获取我的用户密码。两个用户机密共享相同的 json 值。

问题

当我为 ETL 项目设置用户机密并在本地运行它们时,我的发送网格帐户的 API 密钥没有被提取,因为我认为该类是在类库中定义的。

我试过的

我也尝试将相同的用户机密添加到类库中,但这似乎不起作用,我假设这是因为我的类库中没有 appsettings.json,可能不应该有。

4

3 回答 3

1

这里的诀窍是,在 3.1 中,工作服务没有 asp.net nuget 包,也没有明确引用 user-secret nuget 包,这有助于 user-secret 工作。但是在我引用了 user-secrets nuget 包并将以下内容添加到 Program.cs 之后,它开始工作:在此处输入图像描述

于 2020-09-23T21:34:57.817 回答
1

首先,没有必要将用户机密添加到您的类库中,因为没有任何东西会拾取它们。配置系统实际上并不关心您的选项 POCO 存在于哪个程序集中,特别是因为 Microsoft.Extensions.Configuration(这是加载用户机密的位置)仅与 Microsoft.Extensions.Options (您的 POCO为了)。

由于您是通过选项模式使用配置的,只要将依赖注入系统配置为正确地提供配置选项的所有配置源,您的库中的代码就不必担心太多。

因此,如果您在两个(执行)程序集中的用户机密方面遇到问题,那么这与它们的配置方式有关。由于您有一个 ASP.NET Core Web 应用程序和一个辅助服务,我将假设您正在为这两个项目使用主机构建器。在这种情况下,您不必担心设置配置源,因为主机构建器带有一个合理的默认值,其中包含开发模式下的用户机密。

对于它的价值,如果您遇到需要将用户机密配置为配置提供程序,您应该知道IConfigurationBuilder.AddUserSecrets扩展方法通常会期望您传入一个程序集,该程序集从.csproj文件中的项目配置中识别用户机密。– 如果您使用的是默认主机构建器,那么它将为您设置并使用您的项目的程序集,这通常是您想要做的。

正如您自己发现的那样,3.1 存在一个未解决的错误,这将阻止用户机密为 Worker 项目模板开箱即用。原因是底层项目 SDK 忘记处理<UserSecretsId>用于识别用户项目的 MSBuild 属性。

幸运的是,有一个简单的解决方法可以解决这个问题:您需要做的就是添加对Microsoft.Extensions.Configuration.UserSecrets包的显式引用。该包已被Microsoft.Extensions.HostingWorker 项目模板中默认包含的 隐式引用,但通过再次显式添加它,您将启用一些神奇的 MSBuild 位,以使项目正确获取用户机密。

所以你的项目模板应该是这样的:

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UserSecretsId>fb8be4c5-1316-42a7-8c30-3a752ed21c09</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.8" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="3.1.8" />
  </ItemGroup>

</Project>
于 2020-09-23T21:38:45.567 回答
0

请注意,库不能有配置。即使它有一个 DLL 名称的配置文件 - 它也会被忽略。应用程序是那些可以并且应该具有配置的应用程序。两者中的每一个都可以有一个用于 EmailService 的部分,将初始化一个配置类 ( IOptions<T>) 并在 DI 容器中注册。这就是服务将如何获得它,a

应用程序设置.config

{
  "EmailService":
  {
    "somethingStatic": "abc:
  }
}

appsettings.{Env}.config

{
  "EmailService":
  {
    "apiKey": "xyz":
  }
}

启动.cs:

services.Configure<EmailServiceConfig>(context.Configuration.GetSection(EmailServiceConfig.SectionName));

电子邮件服务配置.cs

class EmailServiceConfig
{
  public const string SectionName = nameof(EmailService);

  public string SomethingStatic { get; set; }

  public string ApiKey { get; set; }
}

电子邮件服务.cs:

public EmailService(IOptions<EmailServiceConfig> config
{
}
于 2020-09-23T20:52:24.357 回答