Deep Dive into ASP.NET Core API Project Structure
When you create a new ASP.NET Core Web API project, the framework auto-generates a structured, modern, and production-ready template. Understanding this structure is very important because every real-world API you build will be organized around these key files and folders.
In this chapter, we will explore the purpose of each file, how the request pipeline works, how dependency injection is configured, and how ASP.NET Core organizes controllers, routing, and configuration.
1. Default Project Structure Overview
When you run:
dotnet new webapi -o MyApi
The new folder MyApi contains this structure:
MyApi/
│-- Controllers/
│ └── WeatherForecastController.cs
│-- Properties/
│ └── launchSettings.json
│-- appsettings.json
│-- appsettings.Development.json
│-- Program.cs
│-- MyApi.csproj
│-- WeatherForecast.cs
Let's explore each part in detail.
2. Program.cs — The Heart of Your API
In .NET 6+, the traditional Startup.cs file has been removed. Everything (configuration + middleware + routing) is now inside Program.cs using minimal hosting APIs.
Default Program.cs:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
Key Concepts:
- WebApplicationBuilder → Registers services (DI container)
- WebApplication → Builds the HTTP pipeline
- AddControllers() → Enables Web API controllers
- MapControllers() → Maps routes defined by controllers
- Swagger → Auto-generated API documentation
Service Registration Example:
builder.Services.AddScoped();
builder.Services.AddDbContext(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
3. appsettings.json — The Configuration Hub
This file stores application settings such as:
- Database connection strings
- JWT keys
- Logging configuration
- 3rd-party service keys
Example appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection":
"Server=localhost;Database=MyApiDb;Trusted_Connection=True;"
}
}
How to read a configuration value:
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
4. Environment-Specific Config Files
ASP.NET Core automatically loads config files based on environment:
appsettings.json
appsettings.Development.json
appsettings.Production.json
Check environment in Program.cs:
if (app.Environment.IsDevelopment())
{
Console.WriteLine("Running in Dev Mode...");
}
5. launchSettings.json — Local Run Settings
This file controls how the API runs during development (ports, URLs, profiles).
Example launchSettings.json:
{
"profiles": {
"MyApi": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7123;http://localhost:5123",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
During deployment, this file is ignored because production servers do not use it.
6. Controllers Folder
The Controllers folder contains all your API controller classes. Each controller groups related endpoints.
Example Controller:
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
public IActionResult GetProducts()
{
return Ok(new[] { "Mobile", "Laptop", "Tablet" });
}
}
Understanding Attributes:
- [ApiController] → Enables model validation + routing conventions
- [Route("api/[controller]")] → Dynamic route based on class name
- [HttpGet] → Maps GET requests
7. Models (Entities)
Models represent your database or business objects.
Example:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
8. WeatherForecast.cs — Example Model
The default template includes WeatherForecast.cs to demonstrate model usage.
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
9. Understanding the Middleware Pipeline
The pipeline defines how the request flows through the API.
Example pipeline from Program.cs:
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
Request Flow:
Client → HTTPS redirect → Authentication → Authorization → Controller → Response
10. Adding Custom Middleware
You can add your own middleware for logging, modifying responses, etc.
Custom Middleware Example:
app.Use(async (context, next) =>
{
Console.WriteLine("Request Path: " + context.Request.Path);
await next();
});
11. Dependency Injection Structure
ASP.NET Core uses built-in DI. Services are registered in Program.cs.
Interface:
public interface IEmailService
{
void SendEmail(string message);
}
Implementation:
public class EmailService : IEmailService
{
public void SendEmail(string message)
{
Console.WriteLine("Email Sent: " + message);
}
}
Registering in Program.cs:
builder.Services.AddScoped();
Using in Controller:
private readonly IEmailService _emailService;
public ProductsController(IEmailService emailService)
{
_emailService = emailService;
}
12. Understanding MyApi.csproj File
The project file contains framework version, dependencies, build settings.
Example:
net8.0
enable
enable
Conclusion
Understanding the ASP.NET Core project structure is essential for building clean, scalable, and production-ready APIs. You now know how controllers, middleware, configuration files, dependency injection, and the project file all work together to power your API. In the next chapter, we will learn how controllers, routing, and action methods actually handle incoming HTTP requests.