Skip to main content

Command Palette

Search for a command to run...

Dependency Injection Demystified in ASP.NET Core

Updated
2 min read
Dependency Injection Demystified in ASP.NET Core

Dependency Injection (DI) isn’t just a buzzword. It’s one of the reasons ASP.NET Core apps are clean, testable, and maintainable.

In this article, we’ll break down DI in the most practical way possible with code, real-world usage, and clarity.


🧠 What is Dependency Injection?

Dependency Injection is a design pattern where dependencies (services) are passed into a class rather than the class creating them itself.

Why?
Because it:

  • ✅ Reduces coupling
  • ✅ Increases testability
  • ✅ Improves code flexibility and reuse

🧰 DI in ASP.NET Core: Built-in by Default

ASP.NET Core comes with a built-in IoC (Inversion of Control) container. You register services in Program.cs:

builder.Services.AddScoped<IEmailSender, SmtpEmailSender>();

Then inject them into your classes:

public class AccountController : Controller
{
    private readonly IEmailSender _emailSender;

    public AccountController(IEmailSender emailSender)
    {
        _emailSender = emailSender;
    }
}

ASP.NET Core takes care of creating SmtpEmailSender and passing it in when needed.


🧩 Service Lifetimes

When registering services, choose a lifetime:

// A new instance every time
services.AddTransient<IMyService, MyService>();

// One instance per request
services.AddScoped<IMyService, MyService>();

// One instance for the entire app
services.AddSingleton<IMyService, MyService>();

Choose wisely — especially when dealing with databases or shared state.


💡 Real-world Use Case

Let’s say you want to send SMS via multiple providers (Twilio, Vonage, etc.). You can inject a strategy pattern like this:

public interface ISmsSender { void Send(string to, string message); }
public class TwilioSender : ISmsSender { ... }
public class TermiiSender : ISmsSender { ... }

Register based on config:

if (useTwilio)
    services.AddScoped<ISmsSender, TwilioSender>();
else
    services.AddScoped<ISmsSender, TermiiSender>();

Then inject and call it without knowing which one you got!


🔄 Injecting Configuration

Need to inject app settings?

builder.Services.Configure<MyAppSettings>(
    builder.Configuration.GetSection("MyAppSettings"));

And in your service:

public MyService(IOptions<MyAppSettings> options)
{
    var config = options.Value;
}

🧪 Testability Bonus

DI makes unit testing easy. Just pass in mock dependencies during testing — no hardcoded logic!


✅ Up Next

With DI under your belt, you’re ready to build real APIs with controllers, model validation, and solid error handling.

➡️ Building RESTful APIs the Right Way →

Let’s keep building clean, powerful ASP.NET Core apps 👊

Mastering ASP.NET Core: From Zero to Production

Part 9 of 12

Learn ASP.NET Core by building real-world apps, APIs, and services. This hands-on series takes you from setup to deployment with clean code, cloud integration, and practical tips—perfect for beginners and backend devs alike.

Up next

Routing in ASP.NET Core Made Easy

Routing is how your ASP.NET Core app decides where to send a request — and it’s one of the most important things to understand when building APIs or MVC apps. In this post, we’ll break down routing in ASP.NET Core in the most human way possible. No m...

More from this blog

T

Tunde Hub

40 posts

Sharing practical insights, tools, and tutorials on .NET, ASP.NET Core, cloud, and open source, empowering developers to build with confidence and grow their craft.