1

When you add an appsettings.json file to a project, the following is inserted in its .csproj file:

<ItemGroup>
  <None Update="appsettings.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

with CopyToOutputDirectory being set to either PreserveNewest or Always to ensure the file is copied to the bin\ directory on build. I desire this behaviour for all projects in my repository, so I moved the above lines from the .csproj to a Directory.Build.props file in the repo root. Unfortunately this doesn't work - the directive appears to be ignored by MSBuild and Visual Studio, and the file is indeed not present in the output dir:

appsettings.json not having CopyToOutputDirectory=PreserveNewest set in Visual Studio

I then added a diagnostic message in Directory.Build.props to ensure that appsettings.json exists, and verified that this message appears in VS's Build output for the relevant project:

<Target Name="TestMessage" AfterTargets="Build">
   <Message Condition=Exists('appsettings.json')"
            Text="appsettings.json exists for $(MSBuildProjectFullPath)"
            Importance="high"/>
</Target>

My next thought was that it was something to do with relative versus absolute file paths, so I replaced the relative 'appsettings.json' with its fully-qualified path of $([System.IO.Path]::Combine($(MSBuildProjectDirectory), 'appsettings.json')) - but the result is the same.

Running dotnet msbuild -v:diag seemingly confirms that MSBuild is indeed ignoring the directive from Directory.build.props:

None
   .editorconfig
   appsettings.json

whereas with that directive in the .csproj the output is:

None
   .editorconfig
   appsettings.json
       CopyToOutputDirectory = PreserveNewest

What am I missing, or doing wrong?

1
  • Can you please share a full minimal reproducible example (probably on github or something like that) for a lazy person like me? Commented Oct 22 at 11:30

1 Answer 1

1

I appear to have run afoul of MSBuild's order of operations. Specifically, after moving

<ItemGroup>
  <None Update="appsettings.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

from Directory.Build.props to Directory.Build.targets, appsettings.json is copied to the output directory and appears in VS as expected.

Sign up to request clarification or add additional context in comments.

2 Comments

The Directory.build.props file is auto-imported early - as you realized. When the code is placed in the .props file, you are trying to Update an item that hasn't been Included yet. As a rule of thumb -- avoid using Directory.build.props unless you really need to change something early (which is almost never). If you have MSBuild code that could go into either file, always prefer the Directory.build.targets file.
Thanks Jonathan, it was actually one of your answers on a different question on SO that pointed me down the .targets route versus .props. It's frustrating that Microsoft doesn't explain this better in their docs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.