How to publish environment specific appsettings in

2020-02-08 05:29发布

I have 3 environment specific appsettings files in my .Net core application

enter image description here

in project.json I have setup publishOptions like this. ( based on suggestion here)

"publishOptions": {
    "include": [
      "wwwroot",      
      "appsettings.development.json",
      "appsettings.staging.json",
      "appsettings.production.json",
      "web.config"
    ]
  },

I have 3 corresponding startup classes that uses appropriate appsettings based on environment

var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: false, reloadOnChange: true);

However when I publish the application then all 3 appsettings files end up in all environments. How do I publish environment specific appsetting file?

10条回答
Anthone
2楼-- · 2020-02-08 05:52
        Consider you have multiple appsettings: dev,pre,prod. 
    You can have below configuration in your web project file.

         <!-- This configuration is done for dotnet publish command.
     It will make sure only environment specific files will be copied -->
          <ItemGroup Condition=" '$(EnvironmentName)' == 'Dev'">
            <Content Remove="appsettings.Prod.json" />
            <Content Remove="appsettings.Pre.json" />
          </ItemGroup>
          <ItemGroup Condition=" '$(EnvironmentName)' == 'Pre'">
            <Content Remove="appsettings.Prod.json" />
            <Content Remove="appsettings.Dev.json" />
            <Content Remove="appsettings.Development.json" />
          </ItemGroup>
          <ItemGroup Condition=" '$(**EnvironmentName**)' == 'Prod'">
            <Content Remove="appsettings.Pre.json" />
            <Content Remove="appsettings.Dev.json" />
            <Content Remove="appsettings.Development.json" />
          </ItemGroup>

        This confguration will help during publish. 
    It will not copy the appsettings which is not required for that environment.

        EnvironmentName (part of  <ItemGroup Condition=" '$(**EnvironmentName**)' == 'Prod'">) 
highlighted above should be passed as parameter in below command.

        dotnet publish -o ../../published/20191118A -c release /p:EnvironmentName=Development
查看更多
三岁会撩人
3楼-- · 2020-02-08 05:56

If someone else is wondering how to use different appsettings for multiple environments here is a possible solution.

dotnet publish --configuration [Debug|Release] will copy the appropriate appsettings.json file into the publish folder if *.csproj has a conditional logic for these files:

  • First in the .pubxml publish profile file (can be found in Properties->PublishProfiles of Visual Studio) disable that all content files are included by default
<PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <EnableDefaultContentItems>false</EnableDefaultContentItems>
</PropertyGroup>
  • Then specify conditional Debug/Release logic
<Choose>
    <When Condition="'$(Configuration)' == 'Debug'">
      <ItemGroup>
        <None Include="appsettings.json" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" />
        <None Include="appsettings.prod.json" CopyToOutputDirectory="Never" CopyToPublishDirectory="Never" />
      </ItemGroup>
    </When>
    <When Condition="'$(Configuration)' == 'Release'">
      <ItemGroup>
        <None Include="appsettings.json" CopyToOutputDirectory="Never" CopyToPublishDirectory="Never" />
        <None Include="appsettings.prod.json" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" />
      </ItemGroup>
    </When>
</Choose>
  • Finally inside Startup.cs try to load both files
public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile($"appsettings.prod.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.json", optional: true, reloadOnChange: true)
        .AddEnvironmentVariables();

    Configuration = builder.Build();
}

I hope this solution, has been helpful.

查看更多
Luminary・发光体
4楼-- · 2020-02-08 05:56

Honestly I think that is not the right task for a build pipeline. Also the publishing features of the dotnet cli are very limited. Go to external tools like Tseng showed you. Deployment is another domain with an own set of complexity than building.

There is not a build in way on dotnet cli beyond using external tools!

查看更多
放荡不羁爱自由
5楼-- · 2020-02-08 05:57

One possible way would be to run prepublish or postpublic scripts/commands, for example by running an gulp task executing dotnet publish-iis (alternatively use a task in prepublish section of scripts to copy the files to the before publishing.

Add this to your project.json:

"scripts": {
  "postpublish": [ "gulp cleanconfig", "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}

You can also run a cmd or shell command here. But actually there shouldn't be any reasons why you would want to do this in the first place, just ship all 3 appconfig files, because on i.e. Azure App Service, you can switch the mode depending on the environment variables which is regulated via the Azure Portal and when publishing, the staging and production slots will be just swapped, but the environmental variables stay.

You shouldn't store secrets within the appsettings.json though (which I assume you doe and the reason you want to remove the files). Instead, use "user secrets" for development and environmental variables to set connection strings etc. for production. Works like a charm, especially with Azure App Services and docker containers.

查看更多
Bombasti
6楼-- · 2020-02-08 05:59

I solved this question with this nuget package: https://github.com/Microsoft/slow-cheetah/blob/master/doc/transforming_files.md

It`s so easy for installation and using all configurations in Active solution configuration (In my case - I added a new "Test" configuration for test deployment).

After this you can install this extension in VS: https://marketplace.visualstudio.com/items?itemName=vscps.SlowCheetah-XMLTransforms.

Just now you can create a new config subfiles for .xml or .json application configuration settings in VS by this tool (as in manual). For example, I has Debug, Test, Release files (appsettings.Debug.json and etc.)

Next step - setting up the publish profiles for each configuration and after publishing you will have only one file with all the necessary transformations.

Transformations works like a classic .json envinronment transormation in .net core web applications.

查看更多
虎瘦雄心在
7楼-- · 2020-02-08 06:02

The easiest way i have found so far is to deploy all config files and then remove extra files after the deployment is finished. Just add few extra lines at the end of your deployment shell or batch script.

查看更多
登录 后发表回答