THE ARCHITECTURE LAB

Published

- 5 min read

Copy these 3 "alien" files for maintainable .NET projects

img of Copy these 3 "alien" files for maintainable .NET projects
Reach 13,500+ engaged devs by sponsoring this newsletter

In 2022,

The Christmas came earlier than usual.

Instead of December, it came in August.

Reason?

As an Arsenal fan, while watching the newly released “All or Nothing” documentary about Arsenal, I felt like a child on Christmas morning.

But why am I mentioning this documentary in an email about maintainable .NET projects?

Because in software development, just like in football, to succeed, you must have high standards.

To win trophies, you need to be the very best. And habits and things you do every day in training matter a lot.

To have modern & maintainable projects, you must set high standards in your development process from the start.

And setting the high standards is easier than you think:

Just add these 3 files I’m about to reveal to you.

But before I explain what those 3 files are, let’s quickly review one scene from the “All or Nothing” documentary. In one of the episodes, you see Mikel Arteta, the head coach, upset after losing a football match:

“I accept losing guys, I accept losing. I don’t accept these standards, I’m telling you. I don’t accept them, I don’t accept them, these standards.” Arteta said.

“It’s nowhere near, nowhere near. I’m not criticizing the attitude, but attitude is not enough, courage is not enough, to run is not enough, you have to have much more than that, and it’s nowhere near.

You agree with me, guys? Yeah? But between you do it and demand yourself, that’s what I’m telling you in training because I see it in training, that it doesn’t matter to give the ball away.

It’s okay, sometimes I go to the next ball and I run. No! Because in the game, it’s a goal.

“When I lose a duel, I am upset,” Arteta shouts. “When I lose the small-sided games, I am upset because that’s the standard because you come here and lose.”

You can watch the whole clip below.

He demands more from his players.

And you should demand more from your codebase.

Because when there is pressure, you don’t rise to the level of the occasion. You fall to the level of standards and habits you set.

So, how to implement better habits?

Add these 3 files to every .NET system you work with:

  • Directory.Build.props
  • Directory.Packages.props
  • .editorconfig

Yeah, those files have alien names that don’t sound sexy at all.

But they are useful as hell.

Let me quickly explain them to you.

Directory.Build.props - centralize common settings for easier upgrade

The first alien file we’ll take a look at is the Directory.Build.props file.

It’s an XML file that you put at the root of your solution and contains all the common settings between projects (csproj files), things such as:

  • Target .NET Framework
  • Nullable reference types
  • Code analysis rules
   <Project>
  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
    <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
  </PropertyGroup>

  <!-- Test project specific properties -->
  <PropertyGroup Condition="'$(MSBuildProjectName)' == 'InvadePay.UnitTests' OR
    '$(MSBuildProjectName)' == 'InvadePay.ApiTests'">
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>
</Project>

Once you have it, you can remove all those settings from all your csproj files.

The biggest benefit of the file?

When you have to upgrade your .NET version inside the solution, you don’t have to manually go through 20+ project files. Or instruct AI to change a lot of files and have a massive file diff that no one will want to review.

Instead, you change the TargetFramework once in the Directory.Build.props, and all projects pick up the new version.

Directory.Packages.props - one file to rule all NuGet packages

90% of .NET developers manage NuGet versions the hard way.

Wanna know the secret to managing NuGet packages in large .NET solutions?

Directory.Packages.props.

Aka Central Package Management.

Instead of repeating package version numbers across every project, you define them once in a Directory.Packages.props file:

   <Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>
  <ItemGroup>
    <PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.8" />
    <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.8" />
    <PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" />
    <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.8" />
    <PackageVersion Include="QuestPDF" Version="2025.7.1" />
    <PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
  </ItemGroup>
</Project>

And then each project only references the package name, without the version number:

   <ItemGroup>
  <PackageReference Include="Microsoft.EntityFrameworkCore" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
  <PackageReference Include="QuestPDF" />
  <PackageReference Include="System.IdentityModel.Tokens.Jwt" />
</ItemGroup>

This gives you the following advantages:

  • Consistency across the solution.
  • One place to bump the package version.
  • Saves time every time you upgrade your .NET version.

But fear not.

If you have to override a specific package version in one of your projects, that’s also easy to do:

   <ItemGroup>
  <PackageReference Include="PackageA" VersionOverride="3.0.0" />
</ItemGroup>

Another common question I get when I mention this file is:

“How can I convert my existing project to use the central package management (CPM)?”

A tool I used while I had to convert a complex legacy .NET solution with 60+ projects was CentralisedPackageConverter.

It’s a small tool that lets you do the conversion to CPM through the command line.

.editorconfig - make your codebase look like it was written by a single developer

Ever opened a pull request and half the diff is just whitespace changes?

Different indentation sizes.

Using tabs instead of spaces.

No braces after if statement (I hate those).

Inconsistent usage of the var keyword: 3 times is used, 5 is not.

It’s a nightmare. But it’s completely avoidable.

The .editorconfig file is a simple configuration file that enforces a consistent coding style across your entire team.

You drop it at the root of your solution, and every editor that supports it (spoiler: all major ones do) automatically picks up the rules.

Here’s what you can control:

  • Indentation style and size
  • Line endings
  • Charset
  • Trimming trailing whitespace
  • .NET naming conventions
  • Code style preferences (var vs explicit types, braces, etc.)
  • Autogenerated files to exclude from coding rules
  • And much, much more.

Here’s an example of .editorconfig you can start using in your codebase today.

The end result:

Every file in your codebase will look like it was written by the same person.

Plus, instead of having the coding style fights during PRs, this is now addressed automatically during development. Instead, pull requests become a place to discuss architecture, security, testability, and maintainability.

So there you have it.

3 files with 3 alien names.

Zero excuses not to use them.

Because remember what Arteta said.

Attitude is not enough, courage is not enough, to run is not enough.

You have to have much more than that.

In .NET solutions, “much more” starts with these 3 alien config files.

If you're a .NET developer ready to architect scalable systems...

Every Friday I reveal insights with frameworks, tools & easy-to-implement strategies you can start using almost overnight.

Join the inner circle of 13,500+ .NET developers