I have a solution with a stateless service project (.sfproj) and a corresponding console app project.
I have added appsettings.json to the console app project and am trying to set up access to it using this:
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();
}))
};
}
This doesn't compile because I don't have a Startup
class as it's not a web api project, it's using a stateless service. The only classes I have in the console app are Program.cs
, Service.cs
and ServiceEventSource.cs
I tried removing the .UseStartup<Startup>()
to get it to compile, however when I run the application, I get the following error in 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)
I can fix this by using return this.CreateServiceRemotingInstanceListeners();
instead, however then I don't know how to set up access to appsettings.json.
How can I access appsettings.json
from within my stateless service?
EDIT:
I managed to get it working using this in 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();
}
I added this to ServiceManifest.xml
to make sure env.ContentRootPath
points to the code package folder which contains the appsettings.json
files (the default seems to be the Work folder which was empty for me):
<EntryPoint>
<ExeHost>
<Program>TheAppNameGoesHere.exe</Program>
<WorkingFolder>CodePackage</WorkingFolder>
</ExeHost>
</EntryPoint>
I added this Startup
class:
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{ }
}
I feel like there must be a better way to access appsettings.json
, especially considering the Startup.Configure()
method is doing nothing.
Does anyone know a better way to access appsettings.json
?
it happens because you have to specify the name of the assembly running the app's entry point. The docs explain how should be set.
When you use .UseStartup<Startup>()
it get the assembly information from the Startup
class, because you don't have one, it does not know where the entry point is.
This github issue and this shows similar issues.
This is an example I've got from one of my apps running in SF:
var builder = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureServices(services => services.AddSingleton(startup))
.UseApplicationInsights()
.UseSetting(WebHostDefaults.ApplicationKey, startup.GetType().Assembly.FullName);
In the above example, startup
is an instance of a class that implements Microsoft.AspNetCore.Hosting.IStartup
with following methods:
void Configure(IApplicationBuilder app);
IServiceProvider ConfigureServices(IServiceCollection services);
PS: You don't use .UseStartup<Startup>()
in the example above, but you could if there was one in the project.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.