简体   繁体   中英

Environment variables not being used when debugging through a Service Fabric project

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.

Reference for this answer: https://docs.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.

  1. Add the ASPNETCORE_ENVIRONMENT parameter inside the <Parameters> tag at the top of the file like so:

     <Parameter Name="ASPNETCORE_ENVIRONMENT" DefaultValue="" /> 
  2. 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.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM