Skip to content

Solution Structure

A .NET solution (.sln) groups multiple projects under one umbrella. The standard layout separates source from tests:

MySolution/
├── src/
│   ├── MyApp.API/
│   └── MyApp.Core/
└── tests/
    └── MyApp.Core.Tests/

Each folder is a separate project with its own .csproj file, which defines its type, dependencies, and NuGet packages.

Project Types

Type Output Use for
App (Web API, WinUI…) .exe Entry point of the application
Class Library .dll Shared logic, referenced by other projects

Class libraries have no entry point — they compile to DLLs and are meant to be referenced, not run directly.

Splitting src/

For small projects, two projects are enough: the entry point (App) and a class library for shared logic. As the app grows, src/ is split into more focused projects:

Project Type Responsibility
MyApp.API App Entry point — handles HTTP requests or renders UI
MyApp.Core Class Library Business logic, services, domain models
MyApp.Infrastructure Class Library Database, external APIs, file system

For larger codebases with complex domain logic, a more structured approach separates the domain model, use cases, and infrastructure into distinct layers — see Clean Architecture.

Dependency Injection

DI bindings — the mappings between interfaces and their concrete implementations — are registered in the entry point project:

// Program.cs
builder.Services.AddScoped<IUserRepository, UserRepository>();
// "when someone asks for IUserRepository, give them UserRepository"

This is why the entry point project (MyApp.API) references all other projects: it's the only one that needs to know the full picture to wire everything together. Class libraries only reference what they directly need.

For WPF and WinUI apps, the entry point is App.xaml.cs instead of Program.cs, but the principle is the same.

For the reasoning behind depending on interfaces rather than concrete classes, see SOLID — Dependency Inversion.

Deployment

Once built, there are three ways to run a .NET app:

Runtime-dependent — lightweight build, requires .NET runtime installed on the server:

dotnet publish -c Release
dotnet MyApp.dll

Self-contained — bundles the runtime, runs without prior installation on the target OS:

dotnet publish -c Release --self-contained -r linux-x64

Docker — use an official image that includes the ASP.NET runtime:

FROM mcr.microsoft.com/dotnet/aspnet:9.0

.slnx is a new XML-based solution format in preview, intended to replace the legacy .sln. It's already supported by MSBuild and the .NET CLI, but third-party tools and CI/CD systems may not support it yet. Worth keeping an eye on — widespread adoption is expected once officially released.