Introduction
In modern ASP.NET Core applications, Dependency Injection (DI) and the Repository Pattern are often used together to create clean, maintainable, and testable code.
Repository Pattern abstracts data access logic.
Dependency Injection provides dependencies (like repositories) to controllers or services automatically.
Using both together ensures your Web API is scalable, loosely coupled, and easier to maintain.
This article explains step by step how to implement DI with the Repository Pattern in an ASP.NET Core Web API project.
Step 1: Create a New ASP.NET Core Web API Project
Open a terminal and run:
dotnet new webapi -n DIRepoApi
cd DIRepoApi
dotnet run
This creates a new Web API project that runs at https://localhost:5001.
Step 2: Create the Data Model
Create a Models/User.cs file:
namespace DIRepoApi.Models
{
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
}
This model represents a User entity in the application.
Step 3: Create the Repository Interface
Create a Repositories/IUserRepository.cs file:
using DIRepoApi.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace DIRepoApi.Repositories
{
public interface IUserRepository
{
Task<IEnumerable<User>> GetAllUsersAsync();
Task<User> GetUserByIdAsync(int id);
Task AddUserAsync(User user);
Task UpdateUserAsync(User user);
Task DeleteUserAsync(int id);
}
}
This defines all methods to interact with users.
Notice that there is no database code here, just method signatures.
Step 4: Implement the Repository
Create Repositories/UserRepository.cs:
using DIRepoApi.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace DIRepoApi.Repositories
{
public class UserRepository : IUserRepository
{
private readonly List<User> _users = new List<User>();
public Task<IEnumerable<User>> GetAllUsersAsync() => Task.FromResult(_users.AsEnumerable());
public Task<User> GetUserByIdAsync(int id) => Task.FromResult(_users.FirstOrDefault(u => u.Id == id));
public Task AddUserAsync(User user)
{
user.Id = _users.Count + 1;
_users.Add(user);
return Task.CompletedTask;
}
public Task UpdateUserAsync(User user)
{
var existing = _users.FirstOrDefault(u => u.Id == user.Id);
if (existing != null)
{
existing.Name = user.Name;
existing.Email = user.Email;
}
return Task.CompletedTask;
}
public Task DeleteUserAsync(int id)
{
var user = _users.FirstOrDefault(u => u.Id == id);
if (user != null) _users.Remove(user);
return Task.CompletedTask;
}
}
}
For simplicity, this example uses an in-memory list instead of a database.
You can replace it with EF Core and SQL Server later.
Step 5: Register Repository in Dependency Injection
In Program.cs, add the repository to the DI container:
using DIRepoApi.Repositories;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
// Register repository using Scoped lifetime
builder.Services.AddScoped<IUserRepository, UserRepository>();
var app = builder.Build();
app.MapControllers();
app.Run();

Join the conversation! Your thoughts help the community grow.