Custom Handler (C# Inline)

Handle status codes with an inline C# snippet that composes a JSON payload and writes the response.

Full source

File: pwsh/tutorial/examples/17.4-StatusCodePages-CustomCSharp.ps1

#
# Sample: Status Code Pages with PowerShell Script
# This script demonstrates how to set up a Kestrun server with PowerShell script options.
# The server will use PowerShell scripts to generate custom error responses.
# FileName: 17.4-StatusCodePages-CustomCSharp.ps1
#
param(
    [int]$Port = 5000,
    [IPAddress]$IPAddress = [IPAddress]::Loopback # Use 'Loopback' for safety in tests/examples
)

New-KrLogger | Set-KrLoggerLevel -Level Information |
    Add-KrSinkConsole | Register-KrLogger -Name 'console' -SetAsDefault

# Create a new Kestrun server
New-KrServer -Name 'Status Code Pages with Script Server'

# Add a listener on the specified port and IP address
Add-KrEndpoint -Port $Port -IPAddress $IPAddress

# Create C# script options for status code handling
$code = @'
    var __resp = Context.Response;
    var __req  = Context.Request;

    // Extract request info
    int    __sc    = __resp.StatusCode;
    string __path  = __req.Path.ToString();
    string __meth  = __req.Method;
    string __ua    = __req.Headers["User-Agent"].ToString();

    // Log to console (yellow)
    Console.ForegroundColor = ConsoleColor.Yellow;
    Console.WriteLine($"StatusCode {__sc} for {__meth} {__path}");
    Console.ResetColor();

    // Build response object
    var __payload = new
    {
        error      = true,
        statusCode = __sc,
        path       = __path,
        method     = __meth,
        timestamp  = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"),
        userAgent  = __ua,
        description = __sc switch
        {
            404 => "Page not found - The requested resource does not exist",
            500 => "Internal server error - Something went wrong on our end",
            403 => "Forbidden - You don't have permission to access this resource",
            401 => "Unauthorized - Please authenticate to access this resource",
            _   => $"Error {__sc} occurred"
        },
        suggestion = __sc switch
        {
            404 => "Check the URL or try our home page",
            500 => "Please try again later or contact support",
            403 => "Contact an administrator for access",
            401 => "Please log in to continue",
            _   => "Please try again or contact support"
        }
    };

    // Write JSON response
    __resp.ContentType = "application/json; charset=utf-8";
    __resp.Headers["Cache-Control"] = "no-store, must-revalidate, no-cache, max-age=0";

    await __resp.WriteJsonResponseAsync(__payload,__resp.StatusCode);

'@

# Enable status code pages with PowerShell script
Enable-KrStatusCodePage -Code $code -Language CSharp

# Enable Kestrun configuration
Enable-KrConfiguration

# Map a normal route
Add-KrMapRoute -Verbs Get -Pattern '/hello' -ScriptBlock {
    Write-KrJsonResponse -InputObject @{
        message = 'Hello, World!'
        timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
        status = 'success'
    } -StatusCode 200
}

# Map routes that trigger different status codes
Add-KrMapRoute -Verbs Get -Pattern '/notfound' -ScriptBlock {
    # Return empty response with 404 status to trigger custom error page
    $Context.Response.StatusCode = 404
}

Add-KrMapRoute -Verbs Get -Pattern '/error' -ScriptBlock {
    # Return empty response with 500 status to trigger custom error page
    $Context.Response.StatusCode = 500
}

Add-KrMapRoute -Verbs Get -Pattern '/forbidden' -ScriptBlock {
    # Return empty response with 403 status to trigger custom error page
    $Context.Response.StatusCode = 403
}

Add-KrMapRoute -Verbs Get -Pattern '/unauthorized' -ScriptBlock {
    # Return empty response with 401 status to trigger custom error page
    $Context.Response.StatusCode = 401
}

Write-Host "Server starting on http://$($IPAddress):$Port" -ForegroundColor Green
Write-Host 'Try these URLs:' -ForegroundColor Yellow
Write-Host "  http://$($IPAddress):$Port/hello        - Styled welcome page with test links" -ForegroundColor Cyan
Write-Host "  http://$($IPAddress):$Port/notfound     - Styled 404 error page" -ForegroundColor Cyan
Write-Host "  http://$($IPAddress):$Port/error        - Styled 500 error page" -ForegroundColor Cyan
Write-Host "  http://$($IPAddress):$Port/forbidden    - Styled 403 error page" -ForegroundColor Cyan
Write-Host "  http://$($IPAddress):$Port/unauthorized - Styled 401 error page" -ForegroundColor Cyan
Write-Host "  http://$($IPAddress):$Port/missing      - Styled 404 for unmapped route" -ForegroundColor Cyan


# Start the server asynchronously
Start-KrServer -CloseLogsOnExit

Step-by-step

  1. Logging: Register a console logger.
  2. Code: Provide C# via -Code and -Language CSharp.
  3. Middleware: Enable StatusCodePages with the inline C# code.
  4. Routes: Map /hello and demo routes for 404/500/403/401.
  5. Start: Apply configuration and start the server.

Try it

curl -i http://127.0.0.1:5000/hello
curl -i http://127.0.0.1:5000/notfound
curl -i http://127.0.0.1:5000/error
curl -i http://127.0.0.1:5000/forbidden
curl -i http://127.0.0.1:5000/unauthorized

PowerShell equivalents:

Invoke-WebRequest -Uri http://127.0.0.1:5000/hello | Select-Object StatusCode, Content
Invoke-WebRequest -Uri http://127.0.0.1:5000/notfound    -SkipHttpErrorCheck | Select-Object StatusCode, Content | Format-List
Invoke-WebRequest -Uri http://127.0.0.1:5000/error       -SkipHttpErrorCheck | Select-Object StatusCode, Content | Format-List
Invoke-WebRequest -Uri http://127.0.0.1:5000/forbidden   -SkipHttpErrorCheck | Select-Object StatusCode, Content | Format-List
Invoke-WebRequest -Uri http://127.0.0.1:5000/unauthorized -SkipHttpErrorCheck | Select-Object StatusCode, Content | Format-List

Troubleshooting

Symptom Likely cause Fix
Compile error C# code snippet syntax Validate code uses Context.Response helpers and compiles
No JSON output Forgot to write response Call Context.Response.WriteJsonResponse(...)
Handler not triggered Wrong parameter usage Ensure -Code and -Language CSharp are set on Enable-KrStatusCodePage

References


Previous / Next

Previous: Custom Handler (PowerShell) Next: Content Format