Managing multiple projects in a .NET solution often leads to duplicated configuration across .csproj files. Properties such as target frameworks, nullable settings, language versions, and common package references tend to repeat across projects. This repetition makes maintenance harder and increases the risk of inconsistent configurations.

The Directory.Build.props file in .NET solves this problem by providing a centralized way to define shared MSBuild properties and settings for multiple projects.

In this article, we'll explore what Directory.Build.props is, how it works, and how you can use it to simplify configuration in your .NET solutions.


What is Directory.Build.props?

Directory.Build.props is a special MSBuild configuration file that allows you to define properties and settings that automatically apply to all projects located in the same directory or any subdirectories.

When a .NET project is built, MSBuild searches the directory hierarchy for a file named Directory.Build.props and imports it automatically before the project file is evaluated.

This means you can define common configuration once and have it applied to all projects in your solution.


Why Use Directory.Build.props?

Using Directory.Build.props offers several advantages:

1. Reduce Duplication

Instead of repeating the same settings in every .csproj file, you define them once in a shared location.

2. Ensure Consistency

All projects inherit the same configuration, which helps prevent subtle differences between projects.

3. Simplify Maintenance

Updating shared properties becomes easier because you only need to change them in one place.

4. Clean Project Files

Project files remain minimal and focused on project-specific configuration.


Basic Example

Consider a solution with multiple projects targeting the same framework and using the same compiler settings.

Instead of repeating this configuration in each .csproj file:

<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
  <Nullable>enable</Nullable>
  <ImplicitUsings>enable</ImplicitUsings>
  <LangVersion>latest</LangVersion>
</PropertyGroup>

You can create a Directory.Build.props file in the solution root:

<Project>
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>
</Project>

Now your project files can stay minimal:

<Project Sdk="Microsoft.NET.Sdk">
</Project>

All projects automatically inherit the shared configuration.


Project Structure Example

A typical solution might look like this:

/MySolution
  Directory.Build.props
  /src
    /Api
      Api.csproj
    /Application
      Application.csproj
    /Infrastructure
      Infrastructure.csproj
  /tests
    Api.Tests.csproj

Every project under the root folder automatically receives the settings defined in Directory.Build.props.


Adding Shared Package References

You can also centralize package references used across many projects.

<Project>
  <ItemGroup>
    <PackageReference Include="Serilog" Version="3.0.0" />
    <PackageReference Include="FluentValidation" Version="11.8.0" />
  </ItemGroup>
</Project>

All projects will include these packages automatically.

However, be careful when adding package references globally, as not every project may require them. Consider pairing this approach with Central Package Management for more granular control over versions.


Overriding Properties in a Project

Individual projects can override properties defined in Directory.Build.props.

Example in Directory.Build.props:

<PropertyGroup>
  <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

Override in a specific project:

<PropertyGroup>
  <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>

Project-level configuration always takes precedence.


When to Use Directory.Build.props

This file is most useful when:

  • Working with large multi-project solutions
  • Applying consistent compiler settings
  • Defining common metadata or build settings
  • Sharing common package references

It is especially beneficial in enterprise or microservice architectures where many projects share the same conventions.


Directory.Build.props vs Directory.Build.targets

It's important to understand the difference between these two files:

File Purpose
Directory.Build.props Defines properties imported before project evaluation
Directory.Build.targets Defines build targets imported after project evaluation

In practice:

  • Use props for configuration
  • Use targets for build logic

Best Practices

Here are a few recommended practices when using Directory.Build.props:

  • Keep the file focused on shared configuration
  • Avoid adding too many global package references
  • Place the file at the solution root
  • Use comments to document important settings
  • Combine it with central package management when appropriate

Conclusion

Directory.Build.props is a powerful but often underutilized feature of MSBuild that helps keep .NET solutions clean, consistent, and maintainable. By centralizing shared configuration, you reduce duplication, simplify maintenance, and ensure uniform project settings across your entire solution.

If you are managing multiple projects in a .NET repository, adding a Directory.Build.props file can significantly improve your build configuration and developer experience.