ASP.Net Core: Understanding the framework
The Project Structure Overview
When we create a new solution (e.g., named "MyApi"), Visual Studio generates this hierarchy. We will analyze them in the order they influence our application's lifecycle: from Build → Boot → Run.
MyApi/
├── MyApi.csproj (1. The Build Definition)
├── Properties/
│ └── launchSettings.json (2. The Local Boot Configuration)
├── appsettings.json (3. The Runtime Configuration)
├── appsettings.Development.json (3.1 Dev-specific overrides)
├── Program.cs (4. The Application Logic & Pipeline)
└── MyApi.http (5. The Testing Sandbox)
1. The Project File (.csproj)
Location: Root Folder
Purpose: Defines how the application is compiled.
How to view: Double-click the project name in Solution Explorer.
This is the foundation. It tells the .NET Compiler (Roslyn) what to do.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
</ItemGroup>
</Project>
| Line / Section | Explanation |
<Project Sdk="..."> | The most important attribute. Microsoft.NET.Sdk.Web handles all the complexity. It automatically includes the ASP.NET Core runtime, HTTP libraries, and Kestrel server. Without this, we'd just have a generic console app. |
<TargetFramework> | Specifies .NET 9.0. This determines which version of the Common Language Runtime (CLR) will run our code. |
<Nullable>enable | Safety Feature. This turns on "Nullable Reference Types". If we define a variable string name; and try to set it to null, the compiler will give we a warning. It forces we to write cleaner code (e.g., string? name for nullable). |
<ImplicitUsings> | Code Cleaner. In older .NET, every file needed using System; using System.Linq; etc. This setting tells the compiler to automatically import the most common namespaces for we, keeping our files clutter-free. |
<PackageReference> | Dependencies. This lists external libraries (NuGet packages). The Microsoft.AspNetCore.OpenApi package is new in .NET 9 for generating API documentation. |
2. The Launch Settings (Properties/launchSettings.json)
Location: Properties folder
Purpose: Instructions for Visual Studio on how to start the app on OUR machine.
Note: This file is ignored when we deploy to Production (Azure/AWS).
{
"$schema": "...",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5012",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": { ... }
}
}
profiles: Define the different ways to start the app.http/https: Runs the app using Kestrel (the built-in cross-platform web server). This is the preferred way for modern development.IIS Express: Runs the app nested inside Windows IIS. (Legacy, usually slower).
commandName: "Project": Tells VS to run the executable (MyApi.exe) directly, rather than attaching to IIS.launchUrl: "swagger": When we hit "Play", VS will open Chrome and go tolocalhost:xxxx/swagger.applicationUrl: Defines which port our computer listens on (e.g.,5012).ASPNETCORE_ENVIRONMENT: CRITICAL. This sets the environment variable to"Development".Program.csreads this to decide: "Should I show detailed error stack traces?" (Yes in Dev, No in Prod).
3. The Configuration (appsettings.json)
Location: Root Folder
Purpose: Global settings for the application (Database strings, API Keys, Logging).
We will see two files:
appsettings.json: The base configuration.appsettings.Development.json: Overrides the base config only whenASPNETCORE_ENVIRONMENTis "Development".
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
Logging: Controls the "noise level" in our output window."Default": "Information"means we see general app flow."Microsoft.AspNetCore": "Warning"silences the thousands of internal logs from the framework unless something actually breaks.
AllowedHosts: Security setting."*"means the app accepts requests from any domain name bound to the server IP.
4. The Application Brain (Program.cs)
Location: Root Folder
Purpose: The entry point. It builds the app, configures services, sets up the request pipeline, and starts the server.
In .NET 9, this file uses the Minimal Hosting Model.
Part A: The Builder (Dependency Injection)
Before the app exists, we must define what tools it has available.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddOpenApi();
WebApplication.CreateBuilder(args): This single line initializes the defaults:Reads
appsettings.json.Reads Environment Variables.
Configures Kestrel.
builder.Services: This is the Dependency Injection (DI) Container.If we want to use a Database, we must add it here (
builder.Services.AddDbContext...).If we want to use Auth, we add it here.
AddOpenApi(): Registers the services needed to generate the OpenAPI specification (swagger.json).
Part B: The Pipeline (Middleware)
Once app is built, we define how requests are handled.
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
app.Environment.IsDevelopment(): Checks the variable set inlaunchSettings.json.app.MapOpenApi(): Creates the endpoint that serves the API documentation. We wrap it in theifblock so random public users can't see our API internals in production.app.UseHttpsRedirection(): Security middleware. If a user typeshttp://, this forces them tohttps://.
Part C: The Routes (Endpoints)
This is where the actual work happens.
app.MapGet("/weatherforecast", () =>
{
// ... logic to generate weather data ...
return forecast;
})
.WithName("GetWeatherForecast");
app.Run();
MapGet: Defines a route. "When a user sends a GET request to/weatherforecast, run this function."app.Run(): The final line. It starts the infinite loop that listens for incoming network requests.
5. The Testing File (MyApi.http)
Location: Root Folder
Purpose: A quick way to test our API without leaving Visual Studio.
@MyApi_HostAddress = http://localhost:5012
GET {{MyApi_HostAddress}}/weatherforecast/
Accept: application/json
###
This is a text-based format for sending HTTP requests.
We can click a small "Play" icon directly in this file in Visual Studio to send the request and see the JSON result in a side window. It replaces the need for tools like Postman for simple tests.
Summary of the Flow
Visual Studio reads
.csprojto know how to compile.VS reads
launchSettings.jsonto know which environment variables to set.Program.csstarts:Creates the Builder.
Reads
appsettings.jsonfor config.Registers Services (DI).
Builds the App.
Configures Middleware (Pipeline).
Maps Routes.
Runs the server.