87

In "old school" MSBuild projects - as still used by Windows Forms in VS2017 for example - files could be "nested" via a DependentUpon item in the csproj file.

I used this to group unit tests together in Noda Time, e.g.

<Compile Include="LocalDateTest.PeriodArithmetic.cs">
  <DependentUpon>LocalDateTest.cs</DependentUpon>
</Compile>

That led to easily-navigable tests:

Nested tests

I knowingly "lost" this feature when moving to project.json for .NET Core, but had hoped it would return when converting to MSBuild. However, it looks like MSBuild projects based on the .NET Core SDK (root element <Project Sdk="Microsoft.NET.Sdk">) don't get the same treatment in Visual Studio 2017, even if an ItemGroup is added manually with the same elements as the "old school" project.

ASP.NET Core projects receive automatic nesting for minified CSS and Javascript, but it's not clear how to apply that to C# in .NET Core library projects.

David Pine
  • 21,735
  • 6
  • 69
  • 98
Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929

5 Answers5

107

I have it working in one of my Microsoft.NET.Sdk-style projects using something similar to the following:

<ItemGroup>
  <Compile Update="LocalDateTest.*.cs">
    <DependentUpon>LocalDateTest.cs</DependentUpon>
  </Compile>
</ItemGroup>

The trick here is to use Update instead of Include. This is because the implicit items are coming from a props file that is imported before the main project. An additional Include won't affect files that are already included, but they can be modified using Update.

Matthew King
  • 4,724
  • 2
  • 34
  • 49
  • 2
    Okay, this is bizarre - I'm sure I tried that, and it wasn't working. It now is. Very, very bizarre. Ah - it's the "Update" rather than "Include". – Jon Skeet May 08 '17 at 11:12
  • Habe you tried [this extension](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.FileNesting)? – earloc May 08 '17 at 11:12
  • @AlexanderClare: That link's broken, but I think I know the one you mean - and it didn't work. – Jon Skeet May 08 '17 at 11:13
  • Could I suggest that you point out the difference between this `ItemGroup` and the one in my question? The `Include` vs `Update` attribute is the crucial part. (Will accept when I can anyway, of course.) – Jon Skeet May 08 '17 at 11:15
  • Ok, link should be fixed. But the extension doesn't support ASP.net core, so i guess it doesn't work for other core projecttypes. Would suggest to give it a try, though – earloc May 08 '17 at 11:18
  • 1
    I must admit I'm not exactly sure why the Include vs Update makes the difference. Would love one of the tooling folks to provide some additional info. – Matthew King May 08 '17 at 11:21
  • 2
    @MatthewKing: My *guess* is that it's because `*.cs` is already included by default, and that the nested element content is therefore ignored. – Jon Skeet May 08 '17 at 11:28
  • it does not work in Microsoft.NET.Sdk project. Even explicitly: `Validator.cs` – Pavel Agarkov Feb 10 '18 at 18:23
  • @PavelAgarkov: That works fine for me, and yes, in a Microsoft.NET.Sdk project - see https://github.com/nodatime/nodatime/blob/master/src/NodaTime.Test/NodaTime.Test.csproj for example – Jon Skeet Feb 27 '18 at 16:43
  • 1
    @JonSkeet, yeah... as you said it is bizarre... I tried it one more time in another project and it worked. I do want to nest [tests behind classes they test](https://medium.com/@pavel.agarkov/tests-beside-code-in-net-core-61d4a58e7eb1), but it would be crazy to do it for hundreds of files manually... Even if I write an extension for this - project file won't look good. So I finally decided to always use `Microsoft.NET.Sdk.Web` even for class libraries. Now I don't have to configure nesting at all. – Pavel Agarkov Feb 28 '18 at 08:49
  • @JonSkeet my appsettings files are not nested in VS2017, so I decided to include them in the csproj configuration. But now, ALL the appsettings are saying that end-of-file is expected. Did this happen to you as well? appsettings.json – Zinov Oct 03 '18 at 21:39
  • @Zinov: I don't know what you mean by "ALL the appsettings are saying that end-of-file is expected". But I haven't seen an error like that. – Jon Skeet Oct 03 '18 at 22:54
  • @JonSkeet I was referring to nested appsettings. After doing that change they collapsed into one appsetting file inside the VS2017 but the application didn't compile again due to this errors. The extension that everyone recommended didn't work for me as well. Any thoughts on how to nest the files without this issues? – Zinov Oct 04 '18 at 23:24
  • 1
    Ive just tested this and you need to use the same BuildAction name eg replace 'Compile' with 'Content' or 'None' based on you file properties. In my case it was 'Content' – SM3RKY Nov 13 '18 at 01:11
  • Possibily obvious addition: If you are referring to files in sub folders, separate them with `/`, not \, or it won't work. – Ray Feb 04 '20 at 07:03
12

In Visual Studio 2019, I have a .NET Core 2.2 <Project Sdk="Microsoft.NET.Sdk"> project in which I wanted the nicely-nested appsettings.json / appsettings.Development.json files, just like they do automatically for <Project Sdk="Microsoft.NET.Sdk.Web"> projects.

Here's what I had to add to the .CSPROJ:

  <ItemGroup>
    <Content Include="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
    <Content Include="appsettings.Development.json">
      <DependentUpon>appsettings.json</DependentUpon>
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

After that, I had to unload/reload the project for the change to take effect in Solution Explorer. Note that I also set these files to always be copied to the output directory.

David McClelland
  • 2,563
  • 4
  • 25
  • 35
6

If you want to wildcard it instead of hand-crafting each entry, adding these lines to your .csproj file means that anything like Foo.tests.cs automagically gets nested under Foo.cs

Tested and working in VS2019 with .NET Core 3.1.0

  <ItemGroup>
    <Compile Update="**\*.tests.cs">
      <DependentUpon>$([System.String]::Copy(%(Filename)).Replace(".tests",".cs"))</DependentUpon>
    </Compile>
  </ItemGroup>
Jinlye
  • 808
  • 8
  • 12
2

If you using .netstandardx.x you can not use NestedIn . It's not working.

You can do that manually in your .csproj

<ItemGroup><Compile Include="BaseClass">ChildClass.cs</Compile></ItemGroup>
Batuhan
  • 729
  • 4
  • 20
-6

If you use the same prefix it will nest files automatically.

Example:

AsemblyInfo.cs 
AsemblyInfo.local.cs
Miguel Domingues
  • 414
  • 3
  • 11
  • 1
    The question was about .NET Core. Can you clarify your doubt? – Miguel Domingues Mar 14 '18 at 15:43
  • 2
    Have you tried it in VS2017? I have a solution open right now that has .NetFramework 4.7.1, Core 2.0 and Standard 2.1. I tried adding a Class.cs and then a Class.local.cs in a project of each type. No automatic nesting. Manual nesting works fine. VS2017 (15.7.4) – Andrew Steitz Aug 01 '18 at 18:21
  • Visual Studio 2017 15.9.3: Files with the same prefix are automatically being nested in Solution Explorer – brsfan Jun 27 '19 at 13:32