Using glob patterns in *.csproj files

Make your legacy *.csproj files cleaner and more reliable

Ikechi Michael
2 min readApr 21, 2024

So you inherited a legacy .NET project, or maybe you even wrote one, and when you take a peek in the *.csproj file, you see content like:

<ItemGroup>
<Compile Include="App_Start\Foo.cs" />
<Compile Include="App_Start\Baz.cs" />
<Compile Include="App_Start\WebApiConfig.cs" />
<Compile Include="Areas\HelpPage\ApiDescriptionExtensions.cs" />
<Compile Include="Areas\HelpPage\App_Start\HelpPageConfig.cs" />
<Compile Include="Areas\HelpPage\Controllers\HelpController.cs" />
</ItemGroup>

That’s quite a list, right?
Each <Compile> statement specifies a single C# file to include in the project compilation.
It works, but it can get unwieldy, especially as your project grows. If you use an IDE like Visual Studio or Rider, it’ll track changes to these files and update the *.csproj file for you, but if you use a code editor like VS Code (as many devs including the author are doing more and more these days), you will have to remember to track these changes yourself.

But don’t worry!

There's a more elegant way to handle this using glob patterns.

What are Glob Patterns?

Glob patterns are like wildcard-based rules that match file paths. They let you specify file patterns using wildcards like * and ** to match multiple files with similar characteristics.

In our case, we want to target all C# files (*.cs) within certain directories without listing each file individually.

Simplifying with Glob Patterns

Let’s transform the old-school <Compile> statements into their glob pattern counterparts:

<ItemGroup>
<Compile Include="App_Start\**.cs" />
<Compile Include="Areas\**\*.cs" />
</ItemGroup>

In the first line, App_Start\**.cs tells the compiler to include all C# files (*.cs) within the App_Start directory and its subdirectories. No need to list each file separately anymore!

Similarly, Areas\**\*.cs targets all C# files (*.cs) within any subdirectory of the Areas directory. This is incredibly useful for large projects with nested folder structures.

Feel free to use this for the <Content /> statement too.

<Content Include="Views\**\*.cshtml" CopyToOutputDirectory="PreserveNewest" />

Benefits of Using Glob Patterns

  1. Simplicity: Your .csproj file becomes leaner, cleaner and more maintainable. No more long lists of <Compile> statements cluttering your file.
  2. Flexibility: You can easily adjust the glob patterns to target specific subsets of files or entire directory trees, depending on your project’s needs.

Embrace the Simplicity

Using glob patterns in your old csproj files for compiling *.cs files is a game-changer.

It not only simplifies your project structure but also sets the stage for easier maintenance and scalability as your project evolves.

So go ahead, embrace the simplicity, and let glob patterns work their magic in your .NET projects!

--

--

Ikechi Michael

I’ve learned I don’t know anything. I've also learned that people will pay for what I know. Maybe that's why they never pay.