Skip to content
FullstackCodingGuy edited this page Feb 24, 2025 · 16 revisions

Request Lifecycle in .NET 9

read

🌍 Request Lifecycle in .NET 9

The request lifecycle in a .NET 9 Minimal API / MVC application follows a series of steps from incoming request to response generation. Understanding this helps in performance tuning, debugging, and implementing middleware effectively.


✅ 1. Lifecycle Overview

🔄 Step-by-Step Flow

1️⃣ Client Sends Request → (Browser/Postman/Frontend App)
2️⃣ Kestrel Web Server Receives Request
3️⃣ Middleware Pipeline Processes Request
4️⃣ Routing Determines Controller/Minimal API
5️⃣ Model Binding & Validation (if applicable)
6️⃣ Controller Action / Minimal API Executes
7️⃣ Service Layer Handles Business Logic
8️⃣ Database Interaction Occurs (via Repository/EF Core)
9️⃣ Response Is Generated
🔟 Middleware Pipeline Handles Response
🔟 Response Is Sent Back to Client


✅ 2. Breakdown of Key Stages

🔹 Step 1: HTTP Request Reaches Kestrel

  • Kestrel is the built-in cross-platform web server in ASP.NET.
  • Listens for incoming HTTP requests and forwards them to the middleware pipeline.

🔹 Example:

GET https://localhost:5001/api/expenses

🔹 Step 2: Middleware Pipeline Execution

  • Middleware components process requests in a sequential order.
  • Can short-circuit requests (e.g., authentication, caching).
  • Configured in Program.cs with app.UseMiddleware<>.

🔧 Example Middleware (Logging)

app.Use(async (context, next) =>
{
    Console.WriteLine($"Request: {context.Request.Method} {context.Request.Path}");
    await next(); // Pass request to next middleware
});

Common Middleware in .NET 9

Middleware Purpose
UseExceptionHandler Global error handling
UseRouting Determines request path
UseAuthentication Handles JWT, OAuth, etc.
UseAuthorization Verifies user permissions
UseRateLimiter Throttles requests

🎯 Final Thoughts

  • Understanding the request lifecycle helps optimize performance.
  • Middleware placement is crucial for efficient request processing.
  • Asynchronous programming improves scalability.
  • Database optimizations prevent performance bottlenecks.

This ensures your .NET 9 API is efficient, scalable, and production-ready! 🚀 Let me know if you need further details! 😊

Conditionally Applying Decorators in .NET Dependency Injection?

read

In .NET DI, you can conditionally apply the Decorator Pattern based on configuration or runtime conditions using IServiceCollection.

public class LoggingExpenseServiceDecorator : IExpenseService
{
    private readonly IExpenseService _inner;
    private readonly ILogger<LoggingExpenseServiceDecorator> _logger;

    public LoggingExpenseServiceDecorator(IExpenseService inner, ILogger<LoggingExpenseServiceDecorator> logger)
    {
        _inner = inner;
        _logger = logger;
    }

    public async Task<string> ProcessExpenseAsync(decimal amount)
    {
        _logger.LogInformation($"Processing expense: {amount} USD");

        var result = await _inner.ProcessExpenseAsync(amount);

        _logger.LogInformation($"Expense processed successfully: {result}");

        return result;
    }
}



Conditionally Register the Decorator in Program.cs

var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;

// Register the base service
services.AddScoped<IExpenseService, ExpenseService>();

// Conditionally apply the decorator
bool useLoggingDecorator = builder.Configuration.GetValue<bool>("UseLoggingDecorator");

if (useLoggingDecorator)
{
    services.AddScoped<IExpenseService>(provider =>
    {
        var innerService = provider.GetRequiredService<ExpenseService>();
        var logger = provider.GetRequiredService<ILogger<LoggingExpenseServiceDecorator>>();
        return new LoggingExpenseServiceDecorator(innerService, logger);
    });
}

var app = builder.Build();


Enable/Disable Decorator Using Configuration

{
  "UseLoggingDecorator": true
}


* Set to true → Decorator will be applied.
* Set to false → Only the base service (ExpenseService) will be used.

How to register multiple implementations for the same interface and resolve it?

read

Use of Decorator Pattern

Approach 1

image image image

Approach 2

image

Approach 3 - Using Keyed Services to Register Multiple Implementations of the Same Interface

image image

When to use record in c#

read

In C#, record is a reference type introduced in C# 9 that is primarily used for immutable data models. It provides several benefits over traditional class and struct types, especially when dealing with data-centric applications.


Why Use record in C#?

1️⃣ Immutable Data Modeling

  • record types are designed to be immutable by default.
  • Unlike class, properties cannot be changed after object creation unless explicitly marked as mutable.
public record Person(string Name, int Age);
var person1 = new Person("Alice", 30);
// person1.Age = 31; // ❌ Compilation Error: Properties are readonly by default.

2️⃣ Concise and Readable Syntax

  • Reduces boilerplate code compared to class.
  • Supports primary constructor syntax for easier initialization.
public record Employee(string Name, string Department);

Instead of writing:

public class Employee
{
    public string Name { get; }
    public string Department { get; }
public Employee(string name, string department)
{
    Name = name;
    Department = department;
}

}


3️⃣ Value-Based Equality (Unlike Class)

  • Unlike class, where equality is reference-based, record compares by value.
  • Two records with the same property values are considered equal.
var e1 = new Employee("Bob", "IT");
var e2 = new Employee("Bob", "IT");

Console.WriteLine(e1 == e2); // ✅ True (Value-based equality)

Whereas, with a class:

public class Employee
{
    public string Name { get; }
    public string Department { get; }
public Employee(string name, string department)
{
    Name = name;
    Department = department;
}

}

var c1 = new Employee("Bob", "IT"); var c2 = new Employee("Bob", "IT");

Console.WriteLine(c1 == c2); // ❌ False (Reference-based equality)


4️⃣ Built-in with Expression for Object Copying

  • record supports a with expression for making shallow copies with modifications.
var emp1 = new Employee("Alice", "HR");
var emp2 = emp1 with { Department = "Finance" }; // Copy with modified property

Console.WriteLine(emp1); // Employee { Name = Alice, Department = HR } Console.WriteLine(emp2); // Employee { Name = Alice, Department = Finance }

  • This avoids manually cloning objects in class-based designs.

5️⃣ Supports Inheritance

  • Unlike struct, record supports inheritance.
public record Person(string Name);
public record Employee(string Name, string Role) : Person(Name);
  • Useful when defining domain models with hierarchical relationships.

When to Use record?

Use Case record or class?
Immutable Data Models ✅ record
DTOs (Data Transfer Objects) ✅ record
Configuration Objects ✅ record
Entity Framework Models ❌ class (EF requires mutable properties)
Reference Equality (e.g., Cache, Dependency Injection) ❌ class

Types of record in C#

1️⃣ Positional Record (Primary Constructor)

public record Product(string Name, decimal Price);
  • Auto-generates properties with get accessors.
  • Provides a built-in ToString(), equality, and with expression support.

2️⃣ Classic Record (Like a Class)

public record Product
{
    public string Name { get; init; } = "";
    public decimal Price { get; init; }
}
  • init makes properties settable only during initialization.

3️⃣ Record Struct (record struct)

  • Introduced in C# 10 for value-type record behavior.
public record struct Point(int X, int Y);
  • More memory-efficient for small, frequently used structures.

Conclusion

✅ Use record when:

  • You want immutable and value-based equality behavior.
  • You need concise, readable code with less boilerplate.
  • You require pattern matching and efficient copying with with.
    ❌ Avoid record when:
  • You need mutable objects (prefer class).
  • You work with Entity Framework (EF requires mutable properties).

Would you like a specific example of record usage in an application, such as ASP.NET Core or a REST API? 🚀

References

Clone this wiki locally