Monorepository with C#: Code Organization in .NET Projects

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Monorepository with C#: How to Organize Code in .NET Projects



Modern development with C# and .NET increasingly faces a choice: store all related projects in one repository (monorepository) or split them into separate repositories (multirepository). A monorepository is an approach where the code of multiple applications, libraries, tests, and configurations is stored in a single Git repository. For large enterprise solutions, microservices, or NuGet libraries, this approach can significantly simplify dependency management, refactoring, and deployment.



In this article, we will examine how to properly organize a monorepository with C# in the .NET ecosystem, look at folder structure, project configuration, CI/CD, and best practices.



1. Advantages and Disadvantages of a Monorepository in .NET



Before diving into technical details, it is important to understand when a monorepository is truly useful and when it can become a problem.



Advantages:

  • Single version of dependencies. All projects within the repository use the same package versions, eliminating version conflicts.
  • Simplified refactoring. Changes to a common interface or library API are immediately visible in all projects that use it.
  • Commit integrity. Atomic commits that change both the library and the application work without temporary breaks.
  • Shared settings. One Directory.Build.props file sets compilation settings, code analysis, and versions for all projects.


Disadvantages:

  • Repository size growth. Over time, cloning and history can become very large.
  • CI/CD complexity. A smart build system is required to avoid rebuilding everything on every commit.
  • Access rights. It is more difficult to differentiate access for different teams within one repository.


For .NET projects, a monorepository is especially convenient when you have a shared class library (e.g., Domain or Common), several microservices or web APIs that depend on it.



2. Monorepository Structure for C# (.NET)



Proper folder structure is the foundation of a successful monorepository. Let's look at a typical organization for a solution that includes several microservices, a library, and tests.



MyApp/├── .github/│   └── workflows/│       └── ci.yml├── src/│   ├── MyApp.Common/          # shared library│   │   ├── MyApp.Common.csproj│   │   └── ...│   ├── MyApp.Api.Orders/      # microservice for orders│   │   ├── MyApp.Api.Orders.csproj│   │   └── ...│   └── MyApp.Api.Users/       # microservice for users│       ├── MyApp.Api.Users.csproj│       └── ...├── tests/│   ├── MyApp.Common.Tests/│   │   ├── MyApp.Common.Tests.csproj│   │   └── ...│   └── MyApp.Api.Orders.Tests/│       ├── MyApp.Api.Orders.Tests.csproj│       └── ...├── Directory.Build.props       # shared settings for all projects├── MyApp.sln                   # solution for Visual Studio└── README.md


Key points:

  • All projects are located in the src/ folder, tests in tests/. This is a standard adopted in the .NET community.
  • The Directory.Build.props file sets common properties: TargetFramework, Nullable, ImplicitUsings, package versions, etc.
  • One SLN file simplifies work in the IDE, but with a large number of projects, you can split them into multiple solutions.


Example Directory.Build.props:

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

Blogs

Book Recommendations