Как устанавливается IHostingEnvironment.ContentRootPath?

В моем проекте веб-API Azure Service Fabric я могу добавить свои файлы appsettings.json в свою конфигурацию, используя этот код в своем классе Api.cs:

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return new ServiceInstanceListener[]
        {
            new ServiceInstanceListener(serviceContext =>
                new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                {
                    ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                    return new WebHostBuilder()
                                .UseKestrel()
                                .ConfigureAppConfiguration((builderContext, config) =>
                                {
                                        var env = builderContext.HostingEnvironment;
                                        config.SetBasePath(env.ContentRootPath)
                                            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                                            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                                            .AddEnvironmentVariables();
                                })
                                .ConfigureServices((hostingContext, services) => services
                                .AddSingleton<StatelessServiceContext>(serviceContext)
                                .AddApplicationInsightsTelemetry(hostingContext.Configuration))
                                .UseContentRoot(Directory.GetCurrentDirectory())
                                .UseStartup<Startup>()
                                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                .UseUrls(url)
                                .Build();
                }))
        };
    }

env.ContentRootPath содержит это значение:

C:\SfDevCluster\Data\_App\_Node_0\Abc.IntegrationType_App197\Abc.Integration.ApiPkg.Code.1.0.0

В этой папке я вижу файлы appsettings.json.

Однако в моем проекте службы Azure Service Fabric без сохранения состояния у меня есть этот код в моем классе Service.cs:

    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        Microsoft.AspNetCore.WebHost.CreateDefaultBuilder()
            .ConfigureAppConfiguration((builderContext, config) =>
            {
                var env = builderContext.HostingEnvironment;

                var appName = AppDomain.CurrentDomain.FriendlyName;
                var parentFolderPath = Directory.GetParent(env.ContentRootPath).FullName;
                var packageCodeFolderPath = Path.Combine(parentFolderPath, appName + "Pkg.Code.1.0.0");

                config.SetBasePath(packageCodeFolderPath)
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                    .AddEnvironmentVariables();
            })
            .UseStartup<Startup>()
            .Build()
            .Run();
    }

Здесь env.ContentRootPath содержит это значение:

C:\SfDevCluster\Data\_App\_Node_0\Abc.Integration.OpticalType_App198\work

Однако, поскольку файлы appsettings.json расположены в: C:\SfDevCluster\Data\_App\_Node_0\Abc.Integration.OpticalType_App198\Abc.Integration.Optical.ServicePkg.Code.1.0.0,

Я вынужден создать переменную packageCodeFolderPath, которую вы видите выше.

Это не кажется очень элегантным решением, и я беспокоюсь, что номер версии в Pkg.Code.1.0.0 может измениться (если это вообще номер версии?).

Как установить env.ContentRootPath в качестве пути к папке, содержащей файлы appsettings.json? Или есть лучший способ получить доступ к этим файлам?


person David Klempfner    schedule 24.04.2019    source источник
comment
если env.ContentRootPath указывал на правильный каталог, почему вам нужно было делать Path.Combine() из родительской папки? Почему бы просто не использовать config.SetBasePath(env.ContentRootPath)   -  person Diego Mendes    schedule 24.04.2019
comment
@DiegoMendes env.ContentRootPath не указывает на папку, на которую я хочу указать, а именно на папку с файлами json. Вот почему мне пришлось использовать Path.Combine() и т.д.   -  person David Klempfner    schedule 25.04.2019


Ответы (2)


В манифесте службы вы должны установить WorkingFolder на CodePackage, чтобы для ContentRootPath был установлен код Abc.Integration.Optical.ServicePkg.Code.1.0.0 вместо work.

i.e:

<EntryPoint>
  <ExeHost>
    <Program>myapp.exe</Program>
    <WorkingFolder>CodePackage</WorkingFolder>
  </ExeHost>
</EntryPoint>

Ознакомьтесь с документацией здесь

Другой вариант — получить информацию из переменных среды, установленных SF. Посмотрите здесь: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-environment-variables-reference

Или используйте context.CodePackageActivationContext.WorkDirectory, как предложил Люк в своем ответе.

person Diego Mendes    schedule 25.04.2019

Я рекомендую использовать свойство serviceContext CodePackageActivationContext для поиска SF рабочая папка и используйте ее как ориентир. (Значение Environment.CurrentDirectory варьируется в кластере с 1 узлом и 5 узлами, поэтому оно ненадежно.)

Так что используйте: context.CodePackageActivationContext.WorkDirectory

CodePackageActivationContext также содержит пакет кода version строка (которая действительно является определением версии).

person LoekD    schedule 24.04.2019
comment
Как мне получить доступ к serviceContext в моей службе без сохранения состояния? У меня нет этой переменной в моем коде. У меня также есть этот метод: защищенное переопределение IEnumerable‹ServiceInstanceListener› CreateServiceInstanceListeners() { return this.CreateServiceRemotingInstanceListeners(); } - person David Klempfner; 25.04.2019
comment
Это аргумент, передаваемый конструктору службы, и serviceContext, передаваемый прослушивателю связи, или свойство Service.Context. документы. microsoft.com/en-us/dotnet/api/ - person LoekD; 25.04.2019
comment
Я просмотрел Context.CodePackageActivationContext.WorkDirectory из своего класса службы, но это то же значение, что и env.ContentRootPath - person David Klempfner; 25.04.2019