Solution Structure
A .NET solution (.sln) groups multiple projects under one umbrella. The standard layout separates source from 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.csinstead ofProgram.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:
Self-contained — bundles the runtime, runs without prior installation on the target OS:
Docker — use an official image that includes the ASP.NET runtime:
.slnxis 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.