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

#c# #azure-service-fabric #asp.net-core-2.2

#c# #azure-service-fabric #asp.net-core-2.2

Вопрос:

В моем проекте Azure Service Fabric Web API я могу добавить свои файлы 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:SfDevClusterData_App_Node_0Abc.IntegrationType_App197Abc.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:SfDevClusterData_App_Node_0Abc.Integration.OpticalType_App198work
  

Однако, поскольку appsettings.json файлы расположены в:
C:SfDevClusterData_App_Node_0Abc.Integration.OpticalType_App198Abc.Integration.Optical.ServicePkg.Code.1.0.0 ,

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

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

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

Комментарии:

1. если env.ContentRootPath указывалось на правильный каталог, почему вам нужно было делать Path.Combine() из родительской папки? Почему бы просто не использовать config.SetBasePath(env.ContentRootPath)

2. @DiegoMendes env.ContentRootPath не указывает на папку, на которую я хочу, чтобы она указывала, а именно на папку с файлами json. Вот почему мне пришлось использовать Path. Объединить() и т.д.

Ответ №1:

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

то есть:

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

Проверьте документы здесь

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

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

Ответ №2:

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

Поэтому используйте: context.CodePackageActivationContext.WorkDirectory

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

Комментарии:

1. Как мне получить доступ к ServiceContext в моей службе без состояния? У меня нет этой переменной в моем коде. У меня также есть этот метод: защищенное переопределение IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners() { возвращает это. CreateServiceRemotingInstanceListeners(); }

2. Это аргумент, переданный конструктору службы, а serviceContext переданный прослушивателю связи или Service.Context свойству. learn.microsoft.com/en-us/dotnet/api /…

3. Я взглянул на контекст. CodePackageActivationContext. WorkDirectory из моего класса обслуживания, но это то же значение, что и env.ContentRootPath