ASP.NET Core  

Common Dependency Injection Pitfalls with Scrutor in .NET Minimal APIs

Minimal APIs in ASP.NET Core were designed to reduce ceremony and improve developer productivity. Combined with Scrutor, they enable teams to build clean, scalable applications with minimal boilerplate. However, this combination can also more easily hide Dependency Injection issues than traditional controller-based APIs.

Minimal APIs favor implicit dependency resolution, and Scrutor favors convention-based registration. When both are used together without discipline, small mistakes can turn into runtime bugs that are difficult to diagnose.

This article explores the most common Dependency Injection pitfalls developers face when using Scrutor with .NET Minimal APIs, explains the real-world problems they cause, and shows how to avoid them with clear, production-grade examples.

1. Over-Scanning Assemblies in Minimal APIs

Real-world problem

In Minimal APIs, all configuration often lives in Program.cs. Developers commonly add Scrutor early in development and use broad scanning rules to “just make it work”.

  
    builder.Services.Scan(scan =>
    scan.FromApplicationDependencies()
        .AddClasses()
        .AsImplementedInterfaces()
);
  

Why does this break in production

  • Registers unintended framework and third-party classes

  • Makes DI behavior unpredictable

  • Causes runtime failures when Minimal API endpoints resolve unexpected services

  • Slows application startup

Minimal APIs rely heavily on parameter-based injection. When the container contains unintended registrations, endpoints can silently resolve the wrong implementation.

Correct approach

Scan only assemblies you own and apply strict filters.

builder.Services.Scan(scan =>
    scan.FromAssemblyOf<IApplicationService>()
        .AddClasses(c => c.AssignableTo<IApplicationService>())
        .AsImplementedInterfaces()
        .WithScopedLifetime()
);
  

Minimal APIs benefit the most from precise and intentional DI registration.

2. Hidden Dependency Requirements in Minimal API Endpoints

Real-world problem

Minimal APIs make dependencies invisible because they appear directly in endpoint parameters.

  app.MapGet("/orders", (IOrderService service) =>
{
    return service.GetOrders();
});
  

With Scrutor, the registration logic is often far away from this endpoint.

Why this causes issues

  • Developers forget that endpoints are DI consumers

  • Missing registrations only fail at runtime

  • Refactoring interfaces can silently break endpoints

Correct approach

Always treat Minimal API endpoints as first-class DI consumers. Combine this with startup validation.

  
    builder.Host.UseDefaultServiceProvider(options =>
{
    options.ValidateScopes = true;
    options.ValidateOnBuild = true;
});
  

This ensures missing registrations are caught early.

3. Accidental Multiple Interface Registrations

Real-world problem

A common pattern is tagging services with marker interfaces.

   public class OrderService :
    IOrderService,
    IApplicationService,
    IDisposable
{
}
  

Using Scrutor:

.AsImplementedInterfaces() 

Why this is dangerous

This registers:

  • IOrderService

  • IApplicationService

  • IDisposable

Minimal API endpoints may accidentally resolve services through unintended interfaces, leading to incorrect behavior or runtime ambiguity.

Correct approach

Be explicit about which interface should be exposed.

.AddClasses(c => c.AssignableTo<IApplicationService>())
.As<IOrderService>()
.WithScopedLifetime()

4. Lifetime Mismatches in Minimal APIs

Real-world problem

Minimal APIs often look stateless, which tempts developers to use singletons.

services.AddSingleton<ReportService>();
    public class ReportService
{
    public ReportService(AppDbContext context) { }
}

Why this breaks under load

Minimal API endpoints are executed concurrently. A singleton capturing a scoped dependency like DbContext causes memory leaks, invalid state, and concurrency issues.

Correct approach

Align lifetimes correctly.

services.AddScoped<ReportService>(); 

Minimal APIs do not change DI lifetime rules. Scoped services are still the default for request-based logic.

5. Decorators That Hide Behavior in Minimal APIs

Real-world problem

Decorators are powerful but invisible at endpoint level.

  
    services.Decorate<IOrderService, LoggingOrderService>();
services.Decorate<IOrderService, CachingOrderService>();
  

Endpoint code:

app.MapGet("/orders", (IOrderService service) =>
{
    return service.GetOrders();
});
  

Why this is confusing

  • Endpoint code does not show logging or caching behavior

  • Decorator execution order is not obvious

  • Changing registration order changes runtime behavior

Correct approach

Register decorators together, document their order, and log decorator creation during development.

  
    public CachingOrderService(...)
{
    Console.WriteLine("Caching decorator created");
}
  

Decorator chains should be intentional and discoverable.

6. Mixing Manual and Scrutor Registrations

Real-world problem

Minimal API projects often grow organically.

services.AddScoped<IUserService, UserService>();

services.Scan(scan =>
    scan.FromAssemblyOf<IApplicationService>()
        .AddClasses(c => c.AssignableTo<IApplicationService>())
        .AsImplementedInterfaces()
);
  

Why this causes bugs

The built-in DI container resolves the last registration. Small changes in registration order can change which implementation Minimal API endpoints receive.

Correct approach

Choose one registration strategy per layer. Use Scrutor consistently for application services and repositories, and manual registration only for infrastructure or framework services.

7. Service Locator Anti-Pattern in Minimal APIs

Real-world problem

Minimal APIs allow access to IServiceProvider , which tempts developers to resolve services manually.

app.MapGet("/users", (IServiceProvider provider) =>
{
    var service = provider.GetRequiredService<IUserService>();
    return service.GetAll();
});
  

Why this is harmful

  • Hides dependencies

  • Breaks testability

  • Defeats the purpose of DI

Correct approach

Let Minimal APIs inject dependencies explicitly.

app.MapGet("/users", (IUserService service) =>
{
    return service.GetAll();
}); 

This keeps endpoints readable and test-friendly.

8. Business Logic Inside Decorators

Real-world problem

Decorators are sometimes misused for authorization or business rules.

public class AuthorizationDecorator : IOrderService
{
    public async Task CancelOrder(int id)
    {
        if (!IsAdmin())
            throw new UnauthorizedAccessException();

        await _inner.CancelOrder(id);
    }
}

Why this is a design issue

  • Business rules become invisible at endpoint level

  • Behavior is harder to reason about

  • Violates single responsibility principles

Correct approach

Decorators should handle technical concerns such as logging, caching, metrics, or validation. Business rules should live in core services.

9. Missing DI Validation in Minimal APIs

Real-world problem

Minimal APIs often ship without DI validation because they “look simple”.

Why this causes outages

  • Missing registrations surface only under traffic

  • Lifetime mismatches fail randomly

  • Bugs reach production unnoticed

Correct approach

Always enable DI validation.

  
    builder.Host.UseDefaultServiceProvider(options =>
{
    options.ValidateScopes = true;
    options.ValidateOnBuild = true;
});
  

This is especially important when using Scrutor.

Minimal APIs remove ceremony, and Scrutor removes boilerplate. Together, they also remove visibility. When something goes wrong, debugging becomes harder unless DI rules are strict and intentional.

Key Takeaway

Scrutor works exceptionally well with .NET Minimal APIs, but only when used with discipline. Tight assembly scanning, explicit lifetimes, validated startup configuration, and clear decorator usage are essential.

Minimal APIs do not reduce the importance of good Dependency Injection practices. In fact, they increase it.

Happy Coding!

I write about modern C#, .NET, and real-world development practices. Follow me on C# Corner for regular insights, tips, and deep dives.