Scenario bases Question


1. The Custom Pipeline Scenario: "Your application needs to intercept every incoming request to check for a specific custom header. If missing, it must redirect to a maintenance page without hitting the controller. How do you implement this?

For this scenario, Middleware is the correct choice — not an Action Filter.

Why? Because the requirement is:

  • Inspect every incoming HTTP request
  • Check for a custom header
  • Short-circuit the pipeline early
  • Redirect before MVC/controllers execute

That is exactly what ASP.NET Core middleware is designed for.


Why Middleware is Better Than Action Filters

Middleware Runs Earlier in the Pipeline

Middleware executes before the request reaches MVC.

Pipeline flow:

Request

Middleware

Routing

MVC / Controllers

Action Filters

Controller Action

So if the header is missing:

  • Middleware can stop processing immediately
  • No controller instantiation
  • No model binding
  • No action filters
  • Better performance

Action Filters Are Too Late

Action Filters only execute:

  • After routing
  • Inside MVC
  • Before/after controller actions

Meaning:

  • The request has already entered MVC
  • Resources have already been allocated
  • Controllers are already involved

That violates the requirement:

“without hitting the controller”

So Action Filters are not ideal for this type of global low-level request validation.


Correct Solution Using Middleware

Step 1 — Create Custom Middleware

public class HeaderValidationMiddleware
{
private readonly RequestDelegate _next;

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

public async Task InvokeAsync(HttpContext context)
{
// Check for custom header
if (!context.Request.Headers.ContainsKey("X-App-Maintenance"))
{
// Redirect immediately
context.Response.Redirect("/maintenance");

return; // Stop pipeline execution
}

// Continue to next middleware
await _next(context);
}
}

Step 2 — Register Middleware

In Program.cs:

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.UseMiddleware<HeaderValidationMiddleware>();

app.MapControllers();

app.Run();

What Happens Internally

When a request arrives:

  1. Middleware executes first
  2. Header is checked
  3. If missing:
    • Response redirects
    • Pipeline stops
  4. Controller is never reached

This is called short-circuiting the request pipeline.


Why This Is Architecturally Correct

Middleware is ideal for:

  • Authentication
  • Logging
  • CORS
  • Rate limiting
  • Request validation
  • Global request interception
  • Maintenance mode
  • Header inspection

These are all cross-cutting concerns.

Action Filters are better for:

  • MVC-specific logic
  • Model validation
  • Action execution timing
  • Result modification
  • Authorization tied to controllers/actions

Middleware vs Action Filter Comparison

FeatureMiddlewareAction Filter
Runs before MVC✅ Yes❌ No
Can stop request early✅ Yes⚠️ Limited
Works globally✅ Excellent⚠️ MVC only
Access to raw HTTP pipeline✅ Full❌ Partial
Performance efficient✅ Better❌ More overhead
Controller-independent✅ Yes❌ No
Ideal for header validation✅ Perfect❌ Not ideal


2. The Dependency Injection (DI) Lifecycle: "You have a PriceCalculator service that depends on a CurrencyExchange service. CurrencyExchange fetches data from an external API that changes every minute. What DI lifetimes (Transient, Scoped, Singleton) would you assign to both, and why?

For this scenario, the key is understanding:

  1. How often the data changes
  2. Whether the service holds state
  3. Avoiding lifetime mismatches (captive dependencies)

Scenario Breakdown

You have:

PriceCalculator
↓ depends on
CurrencyExchange
↓ calls external API
Exchange rates change every minute

The important detail is:

Exchange rate data is dynamic and frequently updated.

That strongly affects the DI lifetime choice.


Recommended Lifetimes

ServiceRecommended Lifetime
PriceCalculatorTransient or Scoped
CurrencyExchangeScoped or Transient

Best Practical Choice

CurrencyExchange → Scoped

services.AddScoped<ICurrencyExchange, CurrencyExchange>();

Why Scoped?

A scoped service:

  • Lives for a single HTTP request
  • Avoids repeatedly calling the external API within the same request
  • Still refreshes data on the next request
  • Prevents stale singleton data

This is usually the best balance.


PriceCalculator → Transient

services.AddTransient<IPriceCalculator, PriceCalculator>();

Why Transient?

PriceCalculator:

  • Usually contains no state
  • Just performs calculations
  • Lightweight business logic service

Transient is ideal because:

  • Fresh instance each time
  • No shared mutable state
  • Cheap to create

Why NOT Singleton for CurrencyExchange?

A Singleton would:

  • Be created once for the entire application lifetime
  • Potentially cache stale exchange rates forever
  • Share outdated data across all users

Example problem:

App starts at 9:00 AM
USD/EUR = 0.91

At 10:30 AM:
Real rate = 0.95
Singleton still returns 0.91

That is dangerous for financial systems.


Captive Dependency Problem

A major DI mistake is:

Singleton → depends on Scoped

This is called a captive dependency.

Example:

services.AddSingleton<PriceCalculator>();
services.AddScoped<CurrencyExchange>();

Why this is bad:

  • Singleton lives forever
  • Scoped service lives per request
  • Singleton captures the first scoped instance permanently

Result:

  • Incorrect behavior
  • Memory leaks
  • Stale request data
  • Runtime exceptions in ASP.NET Core

ASP.NET Core may throw:

Cannot consume scoped service from singleton

Correct Lifetime Rules

A service can safely depend on:

Service LifetimeCan Depend On
SingletonSingleton only
ScopedScoped or Singleton
TransientAny lifetime

Recommended Architecture

Option 1 (Most Common)

services.AddTransient<IPriceCalculator, PriceCalculator>();
services.AddScoped<ICurrencyExchange, CurrencyExchange>();

This works because:

  • Transient can depend on Scoped
  • Exchange rates stay consistent during one request
  • Data refreshes naturally across requests

Alternative: Singleton + Internal Cache Refresh

Sometimes CurrencyExchange may be:

services.AddSingleton<ICurrencyExchange, CurrencyExchange>();

BUT only if:

  • It manages its own thread-safe cache
  • Refreshes rates periodically
  • Uses background services/timers
  • Is designed for concurrency

Example:

Singleton service
→ refreshes exchange rates every 60 seconds
→ stores cache safely

This is more advanced and suitable for:

  • High-performance systems
  • Heavy API traffic
  • Centralized caching

But it requires careful thread safety.

3. 

Comments

Popular posts from this blog

TRIGGER in sql server

What is the importance of EDMX file in Entity Framework

Sending Email in asp.net or mvc using gmail or other smpt.