When creating an ASP.NET Core app an environment variable called ASPNETCORE_ENVIRONMENT=Development
will be set for you and when debugging you will see that the IHostingEnvironment
is set to Development
.
The problem is that when I use the same project in a solution set up for Service Fabric the environment variables don't seem to get injected and IHostingEnvironment
just returns "Production".
How can I resolve this?
Note: I've set a breakpoint in the startup class to observe the IHostingEnvironment variable.
From the main menu, select Run | Edit Configurations or choose Edit Configurations from the run/debug configurations selector on the toolbar. In the Run/Debug Configurations dialog, select a configuration you want to add the environment variables to. Type the variable name and value: <name>=<value> .
For developer workstation setup, you can launch Service Fabric Explorer on your local cluster by navigating to https://localhost:19080/Explorer.
To set up a local cluster, press Start and type Service Fabric Local Cluster Manager and press Enter. From system tray right click to the Service Fabric icon and navigate to Setup Local Cluster → 1 Node. Wait few seconds until you see a notification Service Fabric Local Cluster Manager setup completed successfully.
Reference for this answer: https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-manage-multiple-environment-app-configuration
I ran into the same issue with the default template. The following is similar to Duncan's answer but with two important differences: 1) You will not have to change any template code within the service, and 2) the IHostingEnvironment
will be properly set.
First, add the ASPNETCORE_ENVIRONMENT
variable to the <CodePackage>
element of the PackageRoot\ServiceManifest.xml
file of the application service:
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>MyService.exe</Program>
<WorkingFolder>CodePackage</WorkingFolder>
</ExeHost>
</EntryPoint>
<EnvironmentVariables>
<EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value=""/>
</EnvironmentVariables>
</CodePackage>
As in Duncan's response, there are two changes you'll make to the ApplicationManifest.xml
of your Service Fabric Application project. First, setup a parameter (variable) so that it can be modified when the ApplicationParameters
files are substituted based on the way you deploy the project. Then, add an EnvironmentalOverrides
section to your ServiceManifestImport
element. The results of the two additions will look something like this:
<Parameters>
<Parameter Name="MyService_InstanceCount" DefaultValue="-1" />
<Parameter Name="AspNetCoreEnvironment" DefaultValue="" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
<EnvironmentOverrides CodePackageRef="Code">
<EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value="[AspNetCoreEnvironment]" />
</EnvironmentOverrides>
</ServiceManifestImport>
Finally, you can add in the proper values in the individual ApplicationParameters
files:
<Parameters>
<Parameter Name="MyService_InstanceCount" Value="-1" />
<Parameter Name="AspNetCoreEnvironment" Value="Development" />
</Parameters>
At this point, you can remove the variable from your service's Properties - Debug environmental variables.
I ran into the same issue and was able to create a solution that worked for me.
If you look at your ASP.NET Core project, you should see a Program.cs file. At the bottom of it you should see the following interface implementation:
Task<string> ICommunicationListener.OpenAsync(CancellationToken cancellationToken)
{
...
}
You're going to first want to change it to something like the following:
Task<string> ICommunicationListener.OpenAsync(CancellationToken cancellationToken)
{
var context = FabricRuntime.GetActivationContext();
var endpoint = context.GetEndpoint(_endpointName);
var config = context.GetConfigurationPackageObject("Config");
var environment = config.Settings.Sections["Environment"].Parameters["ASPNETCORE_ENVIRONMENT"].Value;
var serverUrl = $"{endpoint.Protocol}://{FabricRuntime.GetNodeContext().IPAddressOrFQDN}:{endpoint.Port}";
_webHost = new WebHostBuilder().UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseEnvironment(environment)
.UseUrls(serverUrl)
.Build();
_webHost.Start();
return Task.FromResult(serverUrl);
}
The key portion is the .UseEnvironment(environment)
call, along with the supporting retrieval of the environment from the configuration. This will give ASP.NET Core the necessary information it needs to choose the environment.
Having done this, you'll obviously need to add the ASPNETCORE_ENVIRONMENT setting to the config section. That looks like the following:
Under your ASP.NET Core project you'll find a directory called PackageRoot/Config. Inside of that there should be a Settings.xml file. Add the following code inside the <Settings>
tag...
<Section Name="Environment">
<Parameter Name="ASPNETCORE_ENVIRONMENT" Value="" />
</Section>
Next, you're going to want to look at the ApplicationPackageRoot/ApplicationManifest.xml file inside the actual Service Fabric Project (this is NOT the ASP.NET Core project). Two file changes are required.
Add the ASPNETCORE_ENVIRONMENT parameter inside the <Parameters>
tag at the top of the file like so:
<Parameter Name="ASPNETCORE_ENVIRONMENT" DefaultValue="" />
Modify your <ServiceManifestImport>
tag to include a <ConfigOverrides>
section like so:
<ConfigOverrides>
<ConfigOverride Name="Config">
<Settings>
<Section Name="Environment">
<Parameter Name="ASPNETCORE_ENVIRONMENT" Value="[ASPNETCORE_ENVIRONMENT]" />
</Section>
</Settings>
</ConfigOverride>
</ConfigOverrides>
Finally, modify your ApplicationParameters/Local.1Node.xml and friends to contain the ASPNETCORE_ENVIRONMENT
parameter:
<Parameter Name="ASPNETCORE_ENVIRONMENT" Value="Development" />
It's a lot of steps to add a freaking variable you can retrieve, but it does allow you a great deal of flexibility and follows the standard Service Fabric pattern to make deployments simple. I hope this helps!
The answer from Duncan worked for me, but there is a small variation for me, maybe due to the version of ASP.NET Core and Service Fabric I use.
I need to override the method CreateServiceInstanceListeners
in my Web Stateless Service.
So that means I'll have this code:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new WebListenerCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting WebListener on {url}");
var environment = FabricRuntime.GetActivationContext()
?.GetConfigurationPackageObject("Config")
?.Settings.Sections["Environment"]
?.Parameters["ASPNETCORE_ENVIRONMENT"]?.Value;
return new WebHostBuilder().UseWebListener()
.ConfigureServices(
services => services
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseEnvironment(environment)
.UseApplicationInsights()
.UseUrls(url)
.Build();
}))
};
}
Of course, you need to set the ASPNETCORE_ENVIRONMENT
variable as explained by Duncan.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With