在无状态asp.net核心服务结构应用程序中读取appsettings.json

时间:2019-06-22 18:22:29

标签: asp.net-core-webapi azure-service-fabric asp.net-core-2.1

我创建了一个asp.net核心2.1 API项目(不在服务结构中),因为如果将此代码添加到ValuesController.cs中,则可以从appsettings.json中检索配置

    private IConfiguration configuration;

    public ValuesController(IConfiguration iConfig)
    {
        configuration = iConfig;
    }
    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        string dbConn = configuration.GetSection("MySettings").GetSection("DbConnection").Value;
        return new string[] { "value1", "value2" };
    }

同一个类似的项目,我创建了一个无状态的asp.net Core API Service Fabric项目,该项目默认情况下不起作用,我必须向appsetting.json添加特定的引用。当我查看该项目时,它们看起来非常相似。这是正确的方法吗?在非服务结构项目中不需要这样做。

return new WebHostBuilder()
                                    .UseKestrel()
                                    .ConfigureAppConfiguration((builderContext, config) =>
                                        {
                                            config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
                                        })
                                    .ConfigureServices(
                                        services => services
                                            .AddSingleton<StatelessServiceContext>(serviceContext))
                                    .UseContentRoot(Directory.GetCurrentDirectory())
                                    .UseStartup<Startup>()
                                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                    .UseUrls(url)
                                    .Build();

1 个答案:

答案 0 :(得分:1)

在Service Fabric内部,我根本不使用应用程序设置。我遵循的方法是将所有服务的所有设置都放在一个位置,即Service Fabric项目中的ApplicationPackageRoot / ApplicationManifest.xml。 因此,例如,如果我有两个服务,ApplicationManifest可能看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="TestAppType" 
ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="Environment" DefaultValue="" />
    <Parameter Name="TestWebApi_InstanceCount" DefaultValue="" />
    <Parameter Name="TestServiceName" DefaultValue="TestService" />
    <Parameter Name="TestService_InstanceCount" DefaultValue="" />
  </Parameters>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="TestServicePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides>
      <ConfigOverride Name="Config">
        <Settings>
          <Section Name="General">
            <Parameter Name="Environment" Value="[Environment]" />
            <Parameter Name="TestServiceName" Value="[TestServiceName]" />
          </Section>
        </Settings>
      </ConfigOverride>
    </ConfigOverrides>
  </ServiceManifestImport>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="TestWebApiPkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides>
      <ConfigOverride Name="Config">
        <Settings>
          <Section Name="General">
            <Parameter Name="Environment" Value="[Environment]" />
          </Section>
        </Settings>
      </ConfigOverride>
    </ConfigOverrides>
  </ServiceManifestImport>
  <DefaultServices>
    <Service Name="TestService" ServicePackageActivationMode="ExclusiveProcess">
      <StatelessService ServiceTypeName="TestServiceType" InstanceCount="[TestService_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
    <Service Name="TestWebApi" ServicePackageActivationMode="ExclusiveProcess">
      <StatelessService ServiceTypeName="TestWebApiType" InstanceCount="[TestWebApi_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>
</ApplicationManifest>

我只是在这里放置了用于应用程序的参数的定义,以及每个服务的特定配置。下一步是为每个放置实数值的环境准备应用程序参数文件,例如Dev.xml:

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/TestApp" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="Environment" Value="Dev" />
    <Parameter Name="TestWebApi_InstanceCount" Value="1" />
    <Parameter Name="TestServiceName" Value="TestService" />
    <Parameter Name="TestService_InstanceCount" Value="-1" />
  </Parameters>
</Application>

在应用程序部署期间,您只需指定要使用的文件即可。 现在要在服务中使用config,您需要为每个服务修改PackageRoot / Config / Settings.xml文件:

<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Section Name="General">
    <Parameter Name="Environment" Value=""/>
    <Parameter Name="TestServiceName" Value=""/>
  </Section>
</Settings>

同样,您在此处未指定值,它们将从ApplicationManifest中获取。您只需要告诉您要使用哪一种服务即可。

现在输入代码。我创建了帮助程序类来检索配置值:

public class ConfigSettings : IConfigSettings
{
    public ConfigSettings(StatelessServiceContext context)
    {
        context.CodePackageActivationContext.ConfigurationPackageModifiedEvent += this.CodePackageActivationContext_ConfigurationPackageModifiedEvent;
        UpdateConfigSettings(context.CodePackageActivationContext.GetConfigurationPackageObject("Config").Settings);
    }

    private void CodePackageActivationContext_ConfigurationPackageModifiedEvent(object sender, PackageModifiedEventArgs<ConfigurationPackage> e)
    {
        this.UpdateConfigSettings(e.NewPackage.Settings);
    }

    public string Environment { get; private set; }
    public string TestServiceName { get; private set; }

    private void UpdateConfigSettings(ConfigurationSettings settings)
    {
        var generalSectionParams = settings.Sections["General"].Parameters;
        Environment = generalSectionParams["Environment"].Value;
        TestServiceName = generalSectionParams["TestServiceName"].Value;
    }
}

public interface IConfigSettings
{
    string Environment { get; }
    string TestServiceName { get; }
}

此类还具有事件订阅,如果在运行服务时更改了配置,则该事件订阅将更新配置。

剩下的是在启动过程中使用服务上下文初始化ConfigSettings并将其添加到内置的ASP.NET CORE容器中,以便可以在其他类中使用它:

.ConfigureServices(services => services
    .AddSingleton<IConfigSettings>(new ConfigSettings(serviceContext)))

编辑:

一旦将配置保存在asp.net核心IoC容器中,就可以通过构造函数注入使用它,如下所示:

public class TestClass
{
    private readonly IConfigSettings _config;

    public TestClass(IConfigSettings config)
    {
        _config = config;
    }

    public string TestMethod()
    {
        return _config.TestServiceName;
    }
}