10

I'm trying to setup a worker service using the asp.net core 3.1 template provided by VS 2019 Enterprise. So far:

1 / Created a new project and ran it: "Hosting Environment: Development", works as expected.

Development

Development

2 / Created a FileSystem publish profile, and added <EnvironmentName>Test</EnvironmentName> to publish the worker to a testing environment for exemple

<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121. 
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <PublishProtocol>FileSystem</PublishProtocol>
    <Configuration>Release</Configuration>
    <Platform>Any CPU</Platform>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <PublishDir>bin\Release\netcoreapp3.1\publish\</PublishDir>
    <EnvironmentName>Test</EnvironmentName>
  </PropertyGroup>
</Project>

When launching the published version, HostingEnvironment is set to "Production", but i defined "Test" in the FolderProfile.pubxml

Production

Production ?

I've tried dotnet publish /p:EnvironmentName=Test, without success.

I also tried to generate manually a web.config file, containing

<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Test" />

The worker service seems to ignore the web.config file.

It works on VS while debugging, having DOTNET_ENVIRONMENT = Test

Test

Test

What's the correct way to publish worker services on different environments ?

Kimba
  • 984
  • 2
  • 9
  • 20
Karuskrokro
  • 103
  • 1
  • 7
  • Where is this hosted? IIS, self hosted? please provide more details. Also there is two environment variables DOTNET_EINVIRONMENT and ASPNETCORE_ENVIRONMENT . Web.config only works when hosting in IIS. Have you checked if the environment variable actually exists in the machine you are publishing to? – Jonathan Alfaro Mar 18 '20 at 16:34
  • The provided screenshots are taken from local debug. The final goal is to host this worker on a Windows Server 2012 R2 as a windows service (and managing different environments), using `Microsoft.Extensions.Hosting.WindowsServices, Version=3.1.1.0`. This approach (having several publication profiles and modifying them for several environments) works for classic ASP.NET Core app's which are hosted on IIS, which uses ASPNETCORE_ENVIRONMENT. The worker service template uses DOTNET_ENVIRONMENT, i'm not sure how to modify and manage that. – Karuskrokro Mar 19 '20 at 08:51
  • Environment Variables are Managed at the Operating System level. Usually how I do it is I have these variables already set to their correct values in the target servers BEFORE I deploy the app. So I might have servers with an environment variable set to "Test" and another server might have "Production". Remember you can have any environment you decide. Meaning you are NOT limited to "Development", "Test","Production" – Jonathan Alfaro Mar 19 '20 at 14:01

1 Answers1

11

My recommended way would be to push the same artifact to all your environments and set the environment variable DOTNET_ENVIRONMENT to your desired value.

SET DOTNET_ENVIRONMENT=test2
dotnet WorkerService1.dll

info: WorkerService1.Worker[0]
      Worker running at: 03/18/2020 17:27:34 +01:00
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: test2

Another way to do it would be to publish a json file alongside your deployment.

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-3.1

// using Microsoft.Extensions.Configuration;

Host.CreateDefaultBuilder(args)
    .ConfigureHostConfiguration(configHost =>
    {
        configHost.SetBasePath(Directory.GetCurrentDirectory());
        configHost.AddJsonFile("hostsettings.json", optional: true);
        configHost.AddEnvironmentVariables(prefix: "PREFIX_");
        configHost.AddCommandLine(args);
    });

The content of your hostsettings.json could be:

{
    "Environment": "test"
}

Now you only need to use the json file that matches your desired target, and copy that next to your DLL.

dotnet WorkerService1.dll

info: WorkerService1.Worker[0]
      Worker running at: 03/18/2020 17:06:03 +01:00
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: test
info: Microsoft.Hosting.Lifetime[0]
Alex AIT
  • 10,190
  • 3
  • 23
  • 49
  • One precision, the goal is to host this Worker on a Windows Server 2012 as a Windows Service using `Microsoft.Extensions.Hosting.WindowsServices, Version=3.1.1.0`. How can you push the Artifact to a desired value while using `sc create / start` ? Otherwise i'll just use a "hostsettings.json" file. – Karuskrokro Mar 19 '20 at 09:03
  • The idea would be to set the environment variable `DOTNET_ENVIRONMENT` for the whole system, e.g. `setx DOTNET_ENVIRONMENT test /M`. If you can't do that or would rather have a self contained solution, you should probably go with the JSON file. – Alex AIT Mar 19 '20 at 09:09
  • 1
    The windows server is hosting both Test & PreProd environments, so i'll stick with the json file, and sadly update the file manually for each deployment (or find a deployment process later which does it). Thanks ! – Karuskrokro Mar 19 '20 at 09:53
  • I have been all over StackOverflow and the interwebs generally trying to find an answer to this and finally I have found a simple straightforward answer. Thank you! – Caltor Dec 07 '20 at 16:18
  • @AlexAIT - The `hostsettings.json` file approach works when I run `dotnet {service}.dll` to start the service after deployment, but not when I use `sc create {service}` then `sc start {service}`. Any ideas why that would be? – Developer Guy Jan 12 '21 at 18:28