Round #477
09 May 2026, 19:35· csharp· qwen2.5-coder-7b-instruct· r13-clean-hints
- Complexity
- band 0
- ZP / UO / OBS
- 2 / 5 / 1
- Journey weight
- 436
- Lightshift ΔL
- +0.00
Prompt
Add global exception handling middleware that maps domain exceptions to HTTP status codes
Zero-point index (what the engine surfaced)
ZPI-ZPI-0001 | 2026-05-09T19:35:38Z
Add global exception handling middleware that maps domain exceptions to HTTP status codes
ZERO POINT — 2 entries (structural invariants)
● hsl(314.84, 100%, 50%) IMiddleware [contract]
● hsl(280.69, 100%, 50%) RequestDelegate [contract]
UNOBSERVED — 5 entries (implied truths)
○ hsl(27.69, 100%, 50%) async [feature]
○ hsl(9.23, 100%, 50%) interface [feature]
○ hsl(77.54, 100%, 42%) Routing middleware [function]
○ hsl(83.08, 100%, 42%) ILogger of T injection [function]
○ hsl(31.38, 100%, 42%) Scoped registration [function]
OBSERVED — 1 entries (explicit in request)
◉ hsl(86.15, 100%, 38%) global [feature]
COMPLEXITY │ 8 entries │ spread: 77° │ band: LOW
Baseline response (no ZPI)
To add global exception handling middleware in a C# ASP.NET Core application that maps domain exceptions to HTTP status codes, you can follow these steps:
1. **Create a custom exception class for your domain exceptions**:
This will help you identify and handle specific types of exceptions.
2. **Implement the middleware**:
Create a middleware that catches all unhandled exceptions and maps them to appropriate HTTP status codes based on the type of exception.
3. **Register the middleware in the `Startup.cs` file**:
Ensure that your middleware is added to the request pipeline so it runs for every request.
Here's a step-by-step implementation:
### Step 1: Create Custom Exception Classes
First, create custom exception classes for your domain exceptions. For example:
```csharp
public class DomainException : Exception
{
public int StatusCode { get; }
public DomainException(string message, int statusCode)
: base(message)
{
StatusCode = statusCode;
}
}
public class NotFoundException : DomainException
{
public NotFoundException(string message)
: base(message, StatusCodes.Status404NotFound)
{
}
}
public class BadRequestException : DomainException
{
public BadRequestException(string message)
: base(message, StatusCodes.Status400BadRequest)
{
}
}
```
### Step 2: Implement the Middleware
Create a middleware that catches all unhandled exceptions and maps them to appropriate HTTP status codes:
```csharp
public class ExceptionHandlingMiddleware
{
private readonly RequestDelegate _next;
public ExceptionHandlingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var code = StatusCodes.Status500InternalServerError;
if (exception is DomainException domainEx)
{
code = domainEx.StatusCode;
}
context.Response.ContentType = "application/json";
context.Response.StatusCode = code;
return context.Response.WriteAsync(new
{
error = exception.Message,
statusCode = code
}.ToString());
}
}
```
### Step 3: Register the Middleware in `Startup.cs`
Register your middleware in the `Configure` method of your `Startup.cs` file:
```csharp
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
// Add the custom exception handling middleware
app.UseMiddleware<ExceptionHandlingMiddleware>();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
```
### Usage Example
Now, you can throw your custom domain exceptions in your controllers or services:
```csharp
[ApiController]
[Route("[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet("{id}")]
public IActionResult Get(int id)
{
if (id == 0)
{
throw new BadRequestException("Invalid product ID");
}
// Simulate a database query that fails
if (!ProductExists(id))
{
throw new NotFoundException($"Product with ID {id} not found");
}
var product = GetProductById(id);
return Ok(product);
}
private bool ProductExists(int id)
{
// Simulated check
return false;
}
private object GetProductById(int id)
{
// Simulated product retrieval
return new { Id = id, Name = "Sample Product" };
}
}
```
With this setup, any unhandled exceptions thrown in your application will be caught by the `ExceptionHandlingMiddleware`, and they will be mapped to appropriate HTTP status codes based on the type of exception.
Enhanced response (with ZPI)
To implement global exception handling middleware that maps domain exceptions to HTTP status codes, we can create a custom middleware. This middleware will catch any exceptions thrown during the request processing and map them to appropriate HTTP status codes based on the type of exception.
Here's how you can implement this:
1. **Create the Custom Middleware:**
```csharp
using Microsoft.AspNetCore.Http;
using System.Net;
using System.Threading.Tasks;
public class ExceptionHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var code = HttpStatusCode.InternalServerError; // 500 if unexpected
switch (exception)
{
case DomainNotFoundException _:
code = HttpStatusCode.NotFound;
break;
case UnauthorizedAccessException _:
code = HttpStatusCode.Unauthorized;
break;
// Add more cases for other domain exceptions
}
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)code;
return context.Response.WriteAsync(new ErrorDetails
{
StatusCode = code,
Message = exception.Message
}.ToString());
}
}
public class ErrorDetails
{
public int StatusCode { get; set; }
public string Message { get; set; }
public override string ToString()
{
return $"{{\"StatusCode\":{StatusCode},\"Message\":\"{Message}\"}}";
}
}
```
2. **Register the Middleware in `Startup.cs`:**
```csharp
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Register the custom exception handling middleware
app.UseMiddleware<ExceptionHandlingMiddleware>();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
```
3. **Define Domain Exceptions:**
```csharp
public class DomainNotFoundException : Exception
{
public DomainNotFoundException(string message) : base(message)
{
}
}
public class UnauthorizedAccessException : Exception
{
public UnauthorizedAccessException(string message) : base(message)
{
}
}
```
### Explanation:
1. **Custom Middleware (`ExceptionHandlingMiddleware`):**
- The middleware catches exceptions thrown during the request processing.
- It maps specific domain exceptions to appropriate HTTP status codes.
- It logs the exception and returns a JSON response with the error details.
2. **Error Details Class:**
- This class is used to format the error response as JSON.
3. **Registration in `Startup.cs`:**
- The middleware is registered in the request pipeline so that it runs for every request.
This implementation provides a robust way to handle exceptions globally and map them to appropriate HTTP status codes, ensuring that clients receive meaningful error responses.
Grader chain
Each grader reads the same baseline + enhanced pair and casts an independent verdict. Disagreement is the framework's own signal — not noise to be averaged away.
V1samba/Meta-Llama-3.3-70B-Instruct
BetterV4qwen2.5-coder-3b-instruct
BetterV5openrouter/qwen/qwen3-235b-a22b-2507
BetterV7qwen2.5-coder-7b-instruct
BetterV8openai/gpt-4.1
SameV9anthropic/claude-opus-4-7
WorseV12openai/gpt-4o
BetterComments
Our grader said what it said. What do you say? Comment as a guest below.
No comments yet. Be the first to say what you make of this round.