Services & Dependency Injection
1. What Is a Service?
A service is a class that contains business logic.
Controllers should:
- Handle HTTP
- Delegate work to services
Services should:
- Do the real work (data access, rules, calculations)
Rule of thumb
Controllers = what happens
Services = how it happens
2. Why Use Services?
- Separation of concerns – controllers stay thin
- Reusability – same service used in many places
- Testability – easy to unit test
- Maintainability – logic lives in one place
3. Basic Service Example
public interface ICitiesService
{
List<string> GetCities();
}
public class CitiesService : ICitiesService
{
public List<string> GetCities()
{
return new() { "London", "Paris", "Tokyo" };
}
}
4. Dependency Injection (DI)
Instead of creating services manually:
new CitiesService(); // ❌
ASP.NET Core injects them for you:
public HomeController(ICitiesService citiesService)
{
_citiesService = citiesService;
}
This is Dependency Injection
5. Registering Services (Program.cs)
builder.Services.AddScoped<ICitiesService, CitiesService>();
That's it. ASP.NET Core handles creation and disposal.
6. DIP, IoC, DI (Easy Explanation)
DIP (Design Principle)
Depend on interfaces, not concrete classes
ICitiesService; // good
CitiesService; // bad dependency
IoC (Concept)
You don't control object creation — the framework does
DI (Implementation)
Dependencies are provided, usually via constructors
public HomeController(ICitiesService service)
7. Service Lifetimes (Very Important)
| Lifetime | Meaning | Use Case |
|---|---|---|
| Transient | New instance every time | Stateless helpers |
| Scoped | One per HTTP request | Most services |
| Singleton | One for entire app | Cache, config |
AddTransient<T>()
AddScoped<T>() // ⭐ most common
AddSingleton<T>()
⚠️ Never inject Scoped into Singleton
8. Injection Types (Know This)
✅ Constructor Injection (Best)
public Controller(IService service)
⚠️ Method / Action Injection
public IActionResult Index([FromServices] IService service)
❌ Property Injection (Rare)
Used sparingly
Interview answer: Constructor injection is preferred
9. Why Interfaces Matter
Interfaces allow:
- Mocking in tests
- Swapping implementations
- Loose coupling
ICitiesService → CitiesService
ICitiesService → FakeCitiesService (tests)
10. Service Scope (Quick)
- ASP.NET Core creates one scope per request
- All scoped services share that instance
- Disposed automatically after request ends
Used for:
- DbContext
- User/session logic
- Transactions
11. Autofac (When Mentioned)
Autofac is a more powerful DI container.
Why use it?
- Advanced registration
- Decorators
- Interceptors
But:
Built-in DI is enough for most apps
12. Common DI Best Practices
- Use interfaces
- Prefer Scoped for services
- Keep services stateless
- Avoid Service Locator
- Don't inject everything "just because"
13. Interview One-Liner 🎯
"Services contain business logic and are injected into controllers using dependency injection. ASP.NET Core's DI container manages lifetimes, promotes loose coupling via interfaces, and improves testability and maintainability."
14. Mental Map 🧠
Controller
↓
Service (interface)
↓
Implementation