Solution Files and Multi-Project Structure

A solution (.sln) is a container that groups multiple related projects together. When you open a solution in Visual Studio or Rider, all member projects are loaded simultaneously, cross-project navigation works, and builds respect project dependencies. From the CLI, dotnet build BlogApp.sln builds all projects in dependency order. Multi-project solutions are the standard for any non-trivial .NET application โ€” separation into projects enforces layer boundaries and makes each project independently testable, independently deployable, and clearly bounded in responsibility.

Creating and Managing Solutions

// โ”€โ”€ Create a solution and add projects โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// Run from terminal:

// Create a blank solution
dotnet new sln -n BlogApp

// Create projects
dotnet new classlib  -n BlogApp.Domain         -o src/BlogApp.Domain
dotnet new classlib  -n BlogApp.Application    -o src/BlogApp.Application
dotnet new classlib  -n BlogApp.Infrastructure -o src/BlogApp.Infrastructure
dotnet new webapi    -n BlogApp.Api            -o src/BlogApp.Api
dotnet new xunit     -n BlogApp.Tests          -o tests/BlogApp.Tests

// Add projects to the solution
dotnet sln BlogApp.sln add src/BlogApp.Domain/BlogApp.Domain.csproj
dotnet sln BlogApp.sln add src/BlogApp.Application/BlogApp.Application.csproj
dotnet sln BlogApp.sln add src/BlogApp.Infrastructure/BlogApp.Infrastructure.csproj
dotnet sln BlogApp.sln add src/BlogApp.Api/BlogApp.Api.csproj
dotnet sln BlogApp.sln add tests/BlogApp.Tests/BlogApp.Tests.csproj

// Add project references (dependency direction: outer depends on inner)
dotnet add src/BlogApp.Application/BlogApp.Application.csproj reference \
    src/BlogApp.Domain/BlogApp.Domain.csproj

dotnet add src/BlogApp.Infrastructure/BlogApp.Infrastructure.csproj reference \
    src/BlogApp.Application/BlogApp.Application.csproj

dotnet add src/BlogApp.Api/BlogApp.Api.csproj reference \
    src/BlogApp.Application/BlogApp.Application.csproj

dotnet add src/BlogApp.Api/BlogApp.Api.csproj reference \
    src/BlogApp.Infrastructure/BlogApp.Infrastructure.csproj

// Build the whole solution
dotnet build BlogApp.sln
Note: The .sln file uses an older, human-unfriendly format maintained by Microsoft โ€” avoid editing it manually. Use dotnet sln add, dotnet sln remove, and dotnet sln list for all solution management operations. IDEs regenerate solution files correctly on project changes. The solution file records the GUIDs, names, and paths of all member projects โ€” if a project moves, update the .sln with the CLI rather than editing the raw XML.
Tip: Use solution folders to organise large solutions โ€” Visual Studio and Rider display solution folders as virtual directory nodes in the project explorer. You can add solution folders with dotnet sln add --solution-folder "Source Projects" src/BlogApp.Api/BlogApp.Api.csproj. Common conventions: src/ for application projects, tests/ for test projects, tools/ for utilities and code generators. This folder convention is used in the ASP.NET Core repository itself and is widely adopted in the .NET ecosystem.
Warning: Circular project references (A references B, B references A) cause build failures. MSBuild resolves the build order based on project references and cannot compile circular dependencies. If you find yourself wanting a circular reference, it usually indicates that the two projects belong in the same project, or that you need a third shared project that both can reference. The solution to circular dependencies is to extract the shared abstraction (usually an interface) into a lower-level project that both can safely reference.

Solution Directory Layout

// Recommended solution directory structure:
// BlogApp/
// โ”œโ”€โ”€ BlogApp.sln
// โ”œโ”€โ”€ .gitignore
// โ”œโ”€โ”€ .editorconfig
// โ”œโ”€โ”€ Directory.Build.props          โ† shared MSBuild properties for all projects
// โ”œโ”€โ”€ Directory.Packages.props       โ† centralised NuGet version management
// โ”œโ”€โ”€ src/
// โ”‚   โ”œโ”€โ”€ BlogApp.Domain/            โ† entities, value objects, domain events
// โ”‚   โ”‚   โ””โ”€โ”€ BlogApp.Domain.csproj
// โ”‚   โ”œโ”€โ”€ BlogApp.Application/       โ† use cases, DTOs, service interfaces
// โ”‚   โ”‚   โ””โ”€โ”€ BlogApp.Application.csproj
// โ”‚   โ”œโ”€โ”€ BlogApp.Infrastructure/    โ† EF Core, email, storage, external APIs
// โ”‚   โ”‚   โ””โ”€โ”€ BlogApp.Infrastructure.csproj
// โ”‚   โ””โ”€โ”€ BlogApp.Api/               โ† controllers, middleware, startup
// โ”‚       โ””โ”€โ”€ BlogApp.Api.csproj
// โ””โ”€โ”€ tests/
//     โ”œโ”€โ”€ BlogApp.Unit.Tests/        โ† unit tests for domain and application
//     โ””โ”€โ”€ BlogApp.Integration.Tests/ โ† integration tests for infrastructure

Common Mistakes

Mistake 1 โ€” Putting all code in a single project (monolith csproj)

โŒ Wrong โ€” one big project with no layer separation; domain logic mixed with HTTP concerns.

โœ… Correct โ€” separate into at minimum Domain, Application, Infrastructure, and API projects.

Mistake 2 โ€” Wrong dependency direction (inner depending on outer)

โŒ Wrong โ€” Domain project references Infrastructure (domain knows about the database).

โœ… Correct โ€” Domain has zero project references; Infrastructure references Application; API references both Application and Infrastructure.

🧠 Test Yourself

The Application layer defines an IPostRepository interface. The Infrastructure layer implements it as EfPostRepository. Which project references which?