#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