Building a REST API with ASP.NET Core (Complete Step-by-Step Guide)
Introduction
ASP.NET Core makes it simple to build fast, secure, and cross-platform REST APIs. In this guide, we’ll walk through everything you need — from project setup to controller creation, data access, and testing your endpoints — using best practices for modern .NET development.
What You’ll Learn
- Create a new ASP.NET Core Web API project
- Understand controllers and routes
- Use Entity Framework Core for database access
- Test endpoints using Swagger or Postman
- Apply dependency injection and best practices
Step 1: Create a New Web API Project
Open a terminal or Visual Studio and run:
dotnet new webapi -n ProductApi
cd ProductApi
This command creates a new API project with built-in Swagger support.
Step 2: Project Structure Overview
You’ll see files like:
Controllers/
Program.cs
appsettings.json
ProductApi.csproj
Program.cs is where your app configuration, routing, and service registration happen.
Step 3: Define a Model
Create a simple Product model inside the Models folder:
namespace ProductApi.Models
{
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public string Category { get; set; } = string.Empty;
}
}
Step 4: Set Up Entity Framework Core
Install EF Core and SQL Server packages:
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
Now, create a new AppDbContext inside the Data folder:
using Microsoft.EntityFrameworkCore;
using ProductApi.Models;
namespace ProductApi.Data
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Product> Products { get; set; }
}
}
Step 5: Configure Database in Program.cs
using Microsoft.EntityFrameworkCore;
using ProductApi.Data;
var builder = WebApplication.CreateBuilder(args);
// Register DbContext
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// Add services
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Middleware
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Update your appsettings.json with a connection string:
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=ProductApiDb;Trusted_Connection=True;TrustServerCertificate=True;"
}
Step 6: Create the Controller
Add a new file ProductsController.cs under the Controllers folder:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ProductApi.Data;
using ProductApi.Models;
namespace ProductApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
private readonly AppDbContext _context;
public ProductsController(AppDbContext context)
{
_context = context;
}
// GET: api/products
[HttpGet]
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
{
return await _context.Products.ToListAsync();
}
// GET: api/products/5
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetProduct(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
return NotFound();
return product;
}
// POST: api/products
[HttpPost]
public async Task<ActionResult<Product>> PostProduct(Product product)
{
_context.Products.Add(product);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
// PUT: api/products/5
[HttpPut("{id}")]
public async Task<IActionResult> PutProduct(int id, Product product)
{
if (id != product.Id)
return BadRequest();
_context.Entry(product).State = EntityState.Modified;
await _context.SaveChangesAsync();
return NoContent();
}
// DELETE: api/products/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteProduct(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
return NotFound();
_context.Products.Remove(product);
await _context.SaveChangesAsync();
return NoContent();
}
}
}
Step 7: Run and Test the API
Start the app using:
dotnet run
Open your browser and navigate to:
https://localhost:5001/swagger
You’ll see the Swagger UI — test all endpoints directly from there!
Step 8: Testing with Postman
- GET:
https://localhost:5001/api/products - POST: Add JSON body:
{ "name": "Laptop", "price": 1200, "category": "Electronics" }
Best Practices
- Use
DTOsto separate domain models from API contracts. - Implement
RepositoryorServicelayers for complex logic. - Enable validation using
[Required]and[Range]attributes. - Use global error handling middleware.
- Secure your endpoints with JWT authentication.
Conclusion
Congratulations! 🎉 You’ve built a fully functional REST API using ASP.NET Core. You now know how to handle CRUD operations, connect to a database, and test APIs using Swagger. Next steps? Add authentication, improve error handling, and deploy to Azure for production use.
Post Tags:
#aspnet-core #csharp #dotnet #webapi #restapi

