Top 25 ASP.NET Core Interviewvragen: Middleware, Dependency Injection en Minimal APIs

Bereid je voor op .NET interviews met deze 25 veelgestelde vragen over ASP.NET Core middleware, dependency injection en Minimal APIs inclusief codevoorbeelden.

ASP.NET Core interviewvragen over middleware, dependency injection en Minimal APIs

De ASP.NET Core-stack blijft een populaire keuze voor enterprise-applicaties en cloud-native ontwikkeling. Tijdens technische sollicitatiegesprekken voor .NET-posities komen vragen over middleware, dependency injection en Minimal APIs regelmatig aan bod. Dit artikel behandelt de 25 meest gestelde interviewvragen over deze onderwerpen, inclusief praktische codevoorbeelden en diepgaande uitleg.

Voorbereiding op ASP.NET Core interviews

Interviewers zoeken naar kandidaten die niet alleen de syntax kennen, maar ook begrijpen waarom bepaalde patronen worden gebruikt. Focus tijdens de voorbereiding op het uitleggen van de onderliggende concepten en trade-offs van elke aanpak.

Middleware in ASP.NET Core

1. Wat is middleware en hoe werkt de request pipeline?

Middleware vormt de ruggengraat van request-verwerking in ASP.NET Core. Elk middleware-component ontvangt een HTTP-request, kan deze verwerken of modificeren, en geeft deze door aan het volgende component in de keten. Deze aanpak creëert een pipeline waarin elke stap specifieke verantwoordelijkheden heeft.

De volgorde van middleware-registratie bepaalt de uitvoeringsvolgorde. Bij een inkomende request doorloopt deze de middleware van boven naar beneden, bij de response van beneden naar boven. Dit bidirectionele gedrag maakt het mogelijk om zowel pre- als post-processing logica te implementeren.

2. Waarom is de volgorde van middleware cruciaal?

De volgorde waarin middleware wordt geregistreerd heeft directe impact op de werking van de applicatie. Een verkeerde volgorde kan leiden tot beveiligingslekken, gemiste excepties of inefficiente request-afhandeling.

Program.cs — Middleware order matterscsharp
var app = builder.Build();

app.UseExceptionHandler("/error");   // 1. Outermost: catches all exceptions
app.UseHsts();                        // 2. HTTP Strict Transport Security
app.UseHttpsRedirection();            // 3. Redirect HTTP to HTTPS
app.UseStaticFiles();                 // 4. Serve static files (short-circuits if found)
app.UseRouting();                     // 5. Match request to endpoint
app.UseAuthentication();              // 6. Identify the user
app.UseAuthorization();               // 7. Check permissions
app.MapControllers();                 // 8. Execute the matched endpoint

app.Run();

De exception handler staat bewust aan het begin van de pipeline. Hierdoor worden excepties van alle onderliggende middleware opgevangen. Static files middleware staat voor authenticatie omdat publieke bestanden geen autorisatie vereisen, wat onnodige overhead voorkomt.

3. Hoe wordt custom middleware geimplementeerd?

Custom middleware biedt de mogelijkheid om cross-cutting concerns te implementeren zonder bestaande code te wijzigen. Een veelvoorkomend voorbeeld is het meten van request-tijden voor performance monitoring.

RequestTimingMiddleware.cscsharp
public class RequestTimingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestTimingMiddleware> _logger;

    public RequestTimingMiddleware(RequestDelegate next, ILogger<RequestTimingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var stopwatch = Stopwatch.StartNew();
        
        await _next(context);  // Call the next middleware
        
        stopwatch.Stop();
        _logger.LogInformation(
            "Request {Method} {Path} completed in {Elapsed}ms",
            context.Request.Method,
            context.Request.Path,
            stopwatch.ElapsedMilliseconds);
    }
}

// Registration in Program.cs
app.UseMiddleware<RequestTimingMiddleware>();

De constructor ontvangt de RequestDelegate die verwijst naar het volgende middleware-component. De InvokeAsync-methode wordt aangeroepen voor elke request en moet expliciet _next aanroepen om de pipeline voort te zetten.

4. Wat is het verschil tussen Use, Map en Run?

Deze drie methoden bepalen hoe middleware zich gedraagt in de pipeline. Use voegt middleware toe die de request doorgeeft aan het volgende component. Run creëert terminal middleware die de pipeline beëindigt. Map vertakt de pipeline op basis van het request-pad.

Terminal middleware met Run is geschikt voor health checks of eenvoudige endpoints die geen verdere verwerking vereisen. Branch middleware met Map maakt het mogelijk om verschillende middleware-stacks te configureren voor verschillende delen van de applicatie.

5. Hoe werkt short-circuiting in middleware?

Short-circuiting treedt op wanneer middleware besluit de request niet door te geven aan het volgende component. Dit is nuttig voor caching, autorisatie-afwijzingen of het serveren van statische bestanden.

Wanneer UseStaticFiles een bestand vindt, retourneert het direct de response zonder de rest van de pipeline te doorlopen. Dit verbetert de performance aanzienlijk voor statische content.

6. Hoe worden excepties globaal afgehandeld?

UseExceptionHandler vangt alle onverwerkte excepties op en retourneert een gestandaardiseerde foutrespons. De plaatsing aan het begin van de pipeline is essentieel zodat excepties van alle onderliggende componenten worden opgevangen. Voor API-applicaties kan een lambda worden geconfigureerd die JSON-foutresponses retourneert.

7. Hoe wordt custom middleware getest?

Unit tests voor middleware vereisen een mock van de RequestDelegate en een test HttpContext. De middleware kan dan worden aangeroepen en het gedrag geverifieerd.

RequestTimingMiddlewareTests.cscsharp
[Fact]
public async Task Middleware_LogsElapsedTime()
{
    var logger = new FakeLogger<RequestTimingMiddleware>();
    var middleware = new RequestTimingMiddleware(
        next: (ctx) => Task.CompletedTask,  // Terminal delegate
        logger: logger);

    var context = new DefaultHttpContext();
    context.Request.Method = "GET";
    context.Request.Path = "/api/products";

    await middleware.InvokeAsync(context);

    Assert.Single(logger.LogEntries);
    Assert.Contains("completed in", logger.LogEntries[0].Message);
}

Een fake logger vangt de log-entries op voor verificatie. De terminal delegate simuleert het einde van de pipeline, waardoor het middleware-gedrag geïsoleerd kan worden getest.

Dependency Injection in .NET

8. Wat zijn de drie service lifetimes en wanneer worden ze gebruikt?

ASP.NET Core ondersteunt drie service lifetimes die bepalen hoe en wanneer instanties worden gecreëerd. Transient services worden bij elke aanvraag opnieuw gecreëerd en zijn geschikt voor lichtgewicht, stateless services. Scoped services bestaan gedurende één HTTP-request en worden gebruikt voor database-contexten en request-specifieke state. Singleton services leven gedurende de gehele applicatie-lifetime en zijn ideaal voor services met dure initialisatie of gedeelde state, mits thread-safe geïmplementeerd.

9. Wat is een captive dependency en hoe wordt dit gedetecteerd?

Een captive dependency ontstaat wanneer een service met langere lifetime een service met kortere lifetime injecteert. Bijvoorbeeld een singleton die een scoped service vasthoudt. Dit veroorzaakt onverwacht gedrag omdat de scoped service langer leeft dan bedoeld.

Program.cs — Captive dependency detectioncsharp
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddSingleton<ICacheService, CacheService>(); // CacheService takes IUserRepository

// This throws at startup in Development when ValidateScopes is enabled:
builder.Host.UseDefaultServiceProvider(options =>
{
    options.ValidateScopes = true;    // Catches captive dependencies
    options.ValidateOnBuild = true;   // Validates all registrations at startup
});

Door scope-validatie in te schakelen worden captive dependencies tijdens development gedetecteerd. Dit voorkomt subtiele bugs die anders pas in productie zouden opduiken.

10. Hoe werken keyed services in .NET 8?

Keyed services maken het mogelijk om meerdere implementaties van dezelfde interface te registreren en specifiek aan te roepen. Dit elimineert de noodzaak voor factory-patronen in veel scenario's.

Program.cs — Registering keyed servicescsharp
builder.Services.AddKeyedSingleton<INotificationService, EmailNotification>("email");
builder.Services.AddKeyedSingleton<INotificationService, SmsNotification>("sms");
builder.Services.AddKeyedSingleton<INotificationService, PushNotification>("push");

// Resolving in a controller or service
public class OrderService
{
    public OrderService(
        [FromKeyedServices("email")] INotificationService emailService,
        [FromKeyedServices("sms")] INotificationService smsService)
    {
        // Each parameter gets its specific implementation
    }
}

Het FromKeyedServices-attribuut specificeert welke implementatie moet worden geïnjecteerd. Dit patroon is bijzonder nuttig voor notificatiesystemen, storage providers of andere scenario's met meerdere implementaties.

11. Wat is het Decorator Pattern met DI?

Het Decorator Pattern voegt functionaliteit toe aan bestaande services zonder hun code te wijzigen. Dit is nuttig voor cross-cutting concerns zoals caching, logging of validatie.

csharp
// Decorating IProductService with caching
builder.Services.AddScoped<ProductService>();
builder.Services.AddScoped<IProductService>(sp =>
{
    var inner = sp.GetRequiredService<ProductService>();
    var cache = sp.GetRequiredService<IMemoryCache>();
    return new CachedProductService(inner, cache);
});

De CachedProductService wrapt de originele ProductService en voegt caching toe. Consumers van IProductService ontvangen automatisch de gedecoreerde versie zonder dat zij hoeven te weten dat caching is toegevoegd.

12. Wanneer wordt constructor injection versus method injection gebruikt?

Constructor injection is de standaard voor verplichte dependencies. Method injection via parameters is geschikt voor optionele dependencies of wanneer de dependency per aanroep kan variëren.

In Minimal APIs en controller-acties ondersteunt ASP.NET Core automatische method injection. Parameters worden automatisch uit de DI-container geresolved, wat de code beknopter maakt.

13. Wat is het verschil tussen IOptions, IOptionsSnapshot en IOptionsMonitor?

IOptions<T> laadt configuratie eenmalig bij de start en is geschikt voor statische instellingen. IOptionsSnapshot<T> herlaadt configuratie per request en is Scoped. IOptionsMonitor<T> is Singleton maar ondersteunt change notifications, ideaal voor langlevende services die moeten reageren op configuratiewijzigingen.

14. Wanneer is IServiceScopeFactory nodig?

IServiceScopeFactory is nodig wanneer Scoped services moeten worden geresolved binnen Singleton-contexten, zoals in Background Services. Het maakt het mogelijk een nieuwe scope te creëren waarbinnen Scoped services correct functioneren.

Klaar om je .NET gesprekken te halen?

Oefen met onze interactieve simulatoren, flashcards en technische tests.

Minimal APIs in ASP.NET Core

15. Wat zijn Minimal APIs en waarom zijn ze geïntroduceerd?

Minimal APIs bieden een lichtgewicht alternatief voor controller-gebaseerde APIs. Ze verminderen de boilerplate code en zijn ideaal voor microservices, prototypes of eenvoudige endpoints. Het framework handelt automatisch model binding, validatie en response-serialisatie af.

16. Hoe worden endpoints georganiseerd met MapGroup?

Naarmate Minimal API-projecten groeien, wordt organisatie cruciaal. MapGroup combineert gerelateerde endpoints en past gedeelde configuratie toe.

Features/Products/ProductEndpoints.cscsharp
public static class ProductEndpoints
{
    public static void MapProductEndpoints(this WebApplication app)
    {
        var group = app.MapGroup("/api/products")
            .WithTags("Products")
            .RequireAuthorization();

        group.MapGet("/", GetAll);
        group.MapGet("/{id:int}", GetById);
        group.MapPost("/", Create);
    }

    private static async Task<IResult> GetAll(
        IProductService productService,    // Auto-resolved from DI
        CancellationToken cancellationToken)
    {
        var products = await productService.GetAllAsync(cancellationToken);
        return TypedResults.Ok(products);
    }

    private static async Task<IResult> GetById(
        int id,
        IProductService productService)
    {
        var product = await productService.GetByIdAsync(id);
        return product is null
            ? TypedResults.NotFound()
            : TypedResults.Ok(product);
    }

    private static async Task<IResult> Create(
        CreateProductRequest request,
        IProductService productService)
    {
        var product = await productService.CreateAsync(request);
        return TypedResults.Created($"/api/products/{product.Id}", product);
    }
}

// Program.cs — Clean registration
app.MapProductEndpoints();

Deze aanpak houdt gerelateerde endpoints bij elkaar en maakt Program.cs overzichtelijk. Extension methods op WebApplication maken modulaire registratie mogelijk.

17. Wat zijn TypedResults en waarom zijn ze belangrijk?

TypedResults retourneren concrete typen in plaats van IResult. Dit verbetert de OpenAPI-documentatie en maakt compile-time verificatie mogelijk. Een endpoint die TypedResults.Ok<Product> retourneert, genereert automatisch het correcte response-schema in de OpenAPI-specificatie.

18. Hoe wordt validatie geïmplementeerd in Minimal APIs?

Minimal APIs ondersteunen verschillende validatie-aanpakken. FluentValidation integreert via endpoint filters. Data annotations werken met de ingebouwde validatieondersteuning. Endpoint filters maken het mogelijk om validatie-logica te centraliseren en hergebruiken over meerdere endpoints.

19. Wanneer worden Minimal APIs versus Controllers gekozen?

Controllers blijven geschikt voor complexe scenario's met veel middleware-configuratie per actie, uitgebreide attribute-gebaseerde routing of wanneer het team bekend is met het MVC-patroon. Minimal APIs excelleren in microservices, serverless functies en scenario's waar snelle opstart en minimale overhead belangrijk zijn.

20. Hoe wordt OpenAPI-documentatie gegenereerd?

Minimal APIs ondersteunen natieve OpenAPI-documentatie via WithOpenApi(), WithDescription() en WithSummary(). Vanaf .NET 9 is de ingebouwde OpenAPI-generator beschikbaar als vervanging voor Swashbuckle, met ondersteuning voor YAML-output en verbeterde schema-generatie.

Geavanceerde Onderwerpen

21. Hoe interageren middleware en endpoint routing?

UseRouting matcht inkomende requests aan endpoints maar voert ze niet uit. Middleware tussen UseRouting en de endpoint-registratie kan de matched endpoint metadata inspecteren. Dit is hoe UseAuthorization de [Authorize]-attributen leest die op controllers of Minimal API endpoints zijn geplaatst.

22. Hoe wordt het circuit breaker pattern geïmplementeerd?

Polly in combinatie met IHttpClientFactory biedt resilience-patronen voor HTTP-communicatie. Circuit breakers voorkomen cascade-failures wanneer externe services niet beschikbaar zijn.

23. Hoe worden health checks geïmplementeerd?

Health checks worden geregistreerd met AddHealthChecks en geëxposeerd via MapHealthChecks. Custom health checks implementeren IHealthCheck en kunnen database-connecties, externe services of andere dependencies verifiëren.

24. Hoe wordt API-versionering aangepakt?

ASP.NET Core ondersteunt URL-segment, query-string en header-gebaseerde versionering. Het Asp.Versioning.Http package biedt uitgebreide ondersteuning voor alle versioneringsstrategieën met integratie in de OpenAPI-documentatie.

25. Hoe worden Background Services met DI geïntegreerd?

Background Services erven van BackgroundService en worden als Hosted Services geregistreerd. Omdat zij een Singleton lifetime hebben, moet IServiceScopeFactory worden gebruikt om Scoped services zoals DbContext correct te resolven.

Best practices voor ASP.NET Core interviews

Demonstreer tijdens het interview begrip van de trade-offs tussen verschillende aanpakken. Leg uit waarom singleton voor caching geschikt is maar gevaarlijk voor database-contexten. Toon kennis van performance-implicaties en testbaarheid.

Conclusie

Een gedegen kennis van ASP.NET Core middleware, dependency injection en Minimal APIs is essentieel voor .NET-ontwikkelaars. De belangrijkste concepten om te beheersen zijn:

  • De middleware pipeline en het belang van de registratievolgorde
  • De drie service lifetimes en hun toepassingsgebieden
  • Captive dependencies detecteren en voorkomen
  • Keyed services voor meerdere implementaties van dezelfde interface
  • Het Decorator Pattern voor cross-cutting concerns
  • MapGroup voor georganiseerde Minimal API endpoints
  • TypedResults voor betere OpenAPI-documentatie
  • Teststrategieën voor middleware en DI-configuraties

Het beheersen van deze concepten verhoogt niet alleen de slagingskans bij technische interviews, maar leidt ook tot beter gestructureerde en onderhoudbare applicaties.

Regelmatige oefening met interviewvragen en praktische codevoorbeelden is de beste voorbereiding. De SharpSkill .NET interview-simulator biedt oefenmodules voor Minimal APIs, Web API-ontwikkeling en clean architecture.

Begin met oefenen!

Test je kennis met onze gespreksimulatoren en technische tests.

Tags

#asp.net core
#interview
#middleware
#dependency injection
#minimal apis
#.net

Delen

Gerelateerde artikelen