如何通过Azure Service Fabric无状态服务访问appsettings.json

时间:2019-04-22 01:51:16

标签: c# azure asp.net-core azure-service-fabric

我有一个无状态服务项目(.sfproj)和相应的控制台应用程序项目的解决方案。

我已将appsettings.json添加到控制台应用程序项目中,并试图使用此设置访问权限:

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    //return this.CreateServiceRemotingInstanceListeners(); //This line works
    return new ServiceInstanceListener[] //This line causes an error in Service Fabric Explorer
    {
        new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                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>() //Startup.cs does not exist
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                    .UseUrls(url)
                    .Build();
            }))
    };
}

这不会编译,因为我没有Startup类,因为它不是Web api项目,它使用的是无状态服务。我在控制台应用程序中仅有的类是Program.csService.csServiceEventSource.cs

我尝试删除.UseStartup<Startup>()使其进行编译,但是,当我运行该应用程序时,在Service Fabric Explorer中出现以下错误:

'System.FM' reported Error for property 'State'.
Partition is below target replica or instance count.
fabric:/Integration/Integration.Service 1 1 9810816d-5be9-4b53-9eed-c5be403219b0
  InBuild _Node_1 132003711574580709
  (Showing 1 out of 1 instances. Total available instances: 0)

我可以改用return this.CreateServiceRemotingInstanceListeners();来解决此问题,但是我不知道如何设置对appsettings.json的访问。

如何从无状态服务中访问appsettings.json

编辑:

我设法在Service.cs中使用它来工作:

        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            Microsoft.AspNetCore.WebHost.CreateDefaultBuilder()
                .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();
                })
                .UseStartup<Startup>()
                .Build()
                .Run();
        }

我将其添加到ServiceManifest.xml中,以确保env.ContentRootPath指向包含appsettings.json文件的代码包文件夹(默认似乎是Work文件夹,对我来说是空的) :

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

我添加了此Startup类:

public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    { }
}

我觉得必须有一种更好的访问appsettings.json的方法,尤其是考虑到Startup.Configure()方法无济于事。

有人知道更好的访问appsettings.json的方法吗?

1 个答案:

答案 0 :(得分:0)

发生这种情况是因为您必须指定运行该应用程序入口点的程序集的名称。 docs解释了如何设置。

当您使用.UseStartup<Startup>()时,它会从Startup类获取程序集信息,因为您没有该信息,所以它不知道入口点在哪里。

This github issuethis显示类似的问题。

这是我从一个在SF中运行的应用中得到的示例:

        var builder = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .ConfigureServices(services => services.AddSingleton(startup))
            .UseApplicationInsights()
            .UseSetting(WebHostDefaults.ApplicationKey, startup.GetType().Assembly.FullName);

在上面的示例中,startup是使用以下方法实现Microsoft.AspNetCore.Hosting.IStartup的类的实例:

    void Configure(IApplicationBuilder app);
    IServiceProvider ConfigureServices(IServiceCollection services);

PS:您在上面的示例中不使用.UseStartup<Startup>(),但是如果项目中有一个,则可以使用。