Every .NET application begins as a project — a collection of source files described by a .csproj file. The .csproj uses the MSBuild XML format but the modern SDK-style format is dramatically simpler than the old full-framework format: typically 5–15 lines rather than 100+. Understanding the project file, the build output structure, and the CLI commands that drive the build lifecycle is foundational knowledge that applies to every project in this series — console applications, class libraries, ASP.NET Core Web APIs, and test projects.
The SDK-Style .csproj File
// ── A minimal ASP.NET Core Web API .csproj ────────────────────────────────
<!-- BlogApp.Api.csproj -->
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<RootNamespace>BlogApp.Api</RootNamespace>
<AssemblyName>BlogApp.Api</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BlogApp.Application\BlogApp.Application.csproj" />
<ProjectReference Include="..\BlogApp.Infrastructure\BlogApp.Infrastructure.csproj" />
</ItemGroup>
</Project>
Sdk attribute determines which implicit build targets and properties are activated. Microsoft.NET.Sdk is for console applications and class libraries. Microsoft.NET.Sdk.Web is for ASP.NET Core applications — it adds web-specific targets like static file copying and enables the Kestrel web server. Microsoft.NET.Sdk.Worker is for background services (Chapter 22). Choosing the wrong SDK causes subtle build failures — if your ASP.NET Core API project uses Microsoft.NET.Sdk, it will not include the web framework bootstrapping targets.<TreatWarningsAsErrors>true</TreatWarningsAsErrors> in all production projects. Compiler warnings are early signals of potential bugs — unused variables, possible null dereferences, deprecated API usage. Treating them as errors prevents “I’ll fix this later” warnings from accumulating into technical debt. Configure specific warning codes to suppress (with <NoWarn>CS1591</NoWarn>) only for intentional cases like XML documentation warnings on internal types.obj or bin directories — these are generated build artefacts and are recreated on every build. Add them to .gitignore (the standard .NET .gitignore template handles this). If you experience inexplicable build errors after a merge, delete the obj directory (dotnet clean or manual deletion) and rebuild — stale generated files are a common cause of hard-to-diagnose build failures.Build Output Structure
// Project directory layout after build:
// BlogApp.Api/
// ├── BlogApp.Api.csproj
// ├── Program.cs
// ├── Controllers/
// │ └── PostsController.cs
// ├── obj/ ← intermediate build files (do not edit, gitignore)
// │ ├── Debug/
// │ └── Release/
// └── bin/ ← compiled output (do not edit, gitignore)
// ├── Debug/
// │ └── net8.0/
// │ ├── BlogApp.Api.dll ← compiled assembly
// │ ├── BlogApp.Api.exe ← entry point (Windows) / launcher script (Linux)
// │ └── BlogApp.Api.deps.json ← dependency manifest
// └── Release/
// └── net8.0/
Top-Level Program.cs (Minimal API Bootstrap)
// Program.cs — the application entry point (top-level statements, no Main method needed)
var builder = WebApplication.CreateBuilder(args);
// ── Register services ─────────────────────────────────────────────────────
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDbContext<AppDbContext>(opts =>
opts.UseSqlServer(builder.Configuration.GetConnectionString("Default")));
var app = builder.Build();
// ── Configure middleware pipeline ─────────────────────────────────────────
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Common Mistakes
Mistake 1 — Wrong SDK for the project type
❌ Wrong — using Microsoft.NET.Sdk for a web project (missing web targets):
✅ Correct — Microsoft.NET.Sdk.Web for ASP.NET Core; Microsoft.NET.Sdk for libraries and console apps.
Mistake 2 — Committing bin and obj to version control
❌ Wrong — binary build artefacts in source control bloat the repository and cause merge conflicts.
✅ Correct — ensure your .gitignore includes bin/ and obj/ at the root and in every project directory.