ASP.NET Core  

Advanced .NET Core Concepts — DI, Middleware & Memory Leaks

Introduction

.NET Core has become the backbone of modern enterprise applications due to its modular architecture, cross-platform support, and high performance.
To build scalable and reliable systems, developers must understand key advanced concepts:

  • Dependency Injection (DI)

  • Middleware Pipeline

  • Memory Leak Prevention

Let's explore each with real-world insights and code examples.

1. Dependency Injection (DI) in .NET Core

What is DI?

Dependency Injection (DI) is a design pattern that helps create loosely-coupled, maintainable applications by providing dependencies instead of manually creating them.

.NET Core has DI built in, unlike older .NET Framework versions, where third-party tools (Autofac, Unity, Ninject) were required.

Types of DI Lifetimes

LifetimePurposeExample
SingletonOne instance throughout app lifeConfig services, cache
ScopedOne instance per requestDB context
TransientNew instance every callLightweight services

Real-Time Example: Registering Services

Service Interface

public interface IMessageService
{
    string SendMessage();
}

Service Implementation

public class EmailService : IMessageService
{
    public string SendMessage() => "Email Sent Successfully!";
}

Registering in the Program.cs

builder.Services.AddScoped<IMessageService, EmailService>();

Injecting in Controller

public class NotificationController : ControllerBase
{
    private readonly IMessageService _messageService;

    public NotificationController(IMessageService messageService)
    {
        _messageService = messageService;
    }

    [HttpGet("send-mail")]
    public string SendMail() => _messageService.SendMessage();
}

DI Best Practices

  • Avoid the service locator pattern

  • Do not inject many services into the constructor (use the Facade pattern)

  • Use the IOptions pattern for configuration

  • Manage lifetimes correctly — Singleton service must not depend on Scoped services

2. Middleware in ASP.NET Core

What is Middleware?

Middleware is a software component added to the HTTP request pipeline to handle:

  • Authentication

  • Logs

  • Exception handling

  • CORS

  • Response compression

Custom Middleware Example

public class RequestLoggingMiddleware
{
    private readonly RequestDelegate _next;

    public RequestLoggingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        Console.WriteLine($"Request: {context.Request.Path}");
        await _next(context);
        Console.WriteLine($"Response: {context.Response.StatusCode}");
    }
}

Register the Middleware

app.UseMiddleware<RequestLoggingMiddleware>();

Middleware Order Matters

app.UseExceptionHandler();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints();

Changing order may break security or routing.

3. Memory Leaks in .NET Core

What Causes Memory Leaks?

Even though .NET has a Garbage Collector, memory leaks still happen due to:

ReasonExample
Unreleased unmanaged resourcesFile handles, database connections
Improper event subscriptionsEvent handlers not removed
Singleton misuseHolding heavy objects
Static referencesCached objects not cleared

Memory Leak Example

public class MyService
{
    private static List<byte[]> _buffer = new();

    public void FillMemory()
    {
        _buffer.Add(new byte[1024 * 1024]); // 1MB
    }
}

Running repeatedly = OutOfMemory

Fix

  • Use DI lifetimes correctly

  • Dispose resources with using

  • Remove event handlers

  • Monitor memory usage with tools:

    • dotMemory

    • PerfView

    • Visual Studio Diagnostic Tools

    • dotnet-counters / dotnet-trace / dotnet-dump

Example cleanup

public class FileService : IDisposable
{
    private FileStream _stream;

    public FileService()
    {
        _stream = File.OpenRead("data.txt");
    }

    public void Dispose()
    {
        _stream?.Dispose();
    }
}

Conclusion

Advanced .NET Core architecture requires developers to understand:

  • Proper DI usage for loose coupling

  • Efficient middleware pipeline

  • Memory management best practices

Mastering these ensures your application stays:

1. Highly scalable

2. Easy to maintain

3.High-performance

Interview Quick-Fire Questions

QuestionKey Concept
What is DI?Loose coupling, easier testing
Difference between AddScoped vs AddSingletonObject lifetime
What is middleware?Request pipeline handlers
How to detect memory leaks?Profilers, GC logs
Why avoid async void?Can't track errors or memory leaks