【问题标题】:reading appsettings.json in stateless asp.net core service fabric application在无状态 asp.net 核心服务结构应用程序中读取 appsettings.json
【发布时间】:2019-11-05 03:59:57
【问题描述】:

我创建了一个 asp.net core 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();

【问题讨论】:

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


    【解决方案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>
    

    在应用程序部署期间,您只需指定要使用的文件。 现在要在服务中使用配置,您需要为每个服务修改 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 Con​​tainer 中,以便你可以在其他类中使用它:

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

    编辑:

    在 asp.net core IoC Container 中配置好配置后,您可以像这样通过构造函数注入来使用它:

    public class TestClass
    {
        private readonly IConfigSettings _config;
    
        public TestClass(IConfigSettings config)
        {
            _config = config;
        }
    
        public string TestMethod()
        {
            return _config.TestServiceName;
        }
    }
    

    【讨论】:

    • 谢谢,这提供了丰富的信息,但您能否在 sn-p 上告诉我在初始化后如何访问代码中的“TestServiceName”?
    猜你喜欢
    • 2022-06-21
    • 1970-01-01
    • 2017-05-25
    • 2019-07-05
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    相关资源
    最近更新 更多