<FodErrorPopup
ErrorReport="@_errorReport"
ShowTechnicalDetails="true"
ShowRetryButton="true"
ShowContactSupportButton="true"
MaxRetryAttempts="3"
OnRetry="HandleRetry"
OnDismiss="HandleDismiss"
OnContactSupport="HandleContactSupport" />
@code {
private FodErrorReport? _errorReport;
private void ShowError(HttpResponseMessage response)
{
_errorReport = new FodErrorReport
{
ErrorId = ErrorIdGenerator.Generate(),
StatusCode = (int)response.StatusCode,
ErrorTitle = "Request Failed",
UserFriendlyMessage = "Please try again later.",
RequestUrl = response.RequestMessage?.RequestUri?.ToString(),
Timestamp = DateTime.UtcNow
};
}
}FodErrorHandler
Enterprise error handling with retry logic, circuit breaker pattern, and PII masking. Demonstrates resilient error management for distributed systems.
Error Popup
Modal popup for displaying HTTP errors with retry, technical details, and contact support options.
Error Boundary
Graceful error recovery UI for unhandled exceptions with recovery actions and error ID tracking.
Note: In Blazor .NET 8 with render modes, each interactive page should wrap its content with FodErrorBoundary to catch render exceptions. The popup will show when an unhandled exception occurs.
<!-- In Routes.razor - wraps entire application -->
<FodErrorBoundary>
<ChildContent>
<Router AppAssembly="typeof(Routes).Assembly">
...
</Router>
</ChildContent>
</FodErrorBoundary>
<!-- Custom error content (optional) -->
<FodErrorBoundary OnError="HandleError">
<ChildContent>
<YourComponent />
</ChildContent>
<ErrorContent Context="errorReport">
<div class="my-custom-error">
<h2>Error: @errorReport.ErrorId</h2>
<p>@errorReport.UserFriendlyMessage</p>
</div>
</ErrorContent>
</FodErrorBoundary>
@code {
private void HandleError(FodErrorReport report)
{
Console.WriteLine($"Error caught: {report.ErrorId}");
}
}PII Masking
Automatically mask personally identifiable information (IDNP, phone, email, IDNO) in error reports for GDPR compliance.
@inject IFodPiiMaskingService PiiMaskingService
@code {
private void MaskSensitiveData()
{
// IDNP: "1234567890123" -> "1234567****23"
var maskedIdnp = PiiMaskingService.MaskIdnp("1234567890123");
// Phone: "+37369123456" -> "******3456"
var maskedPhone = PiiMaskingService.MaskPhone("+37369123456");
// Email: "john.doe@example.com" -> "jo***@example.com"
var maskedEmail = PiiMaskingService.MaskEmail("john.doe@example.com");
// IDNO: "1003600123456" -> "1003*********"
var maskedIdno = PiiMaskingService.MaskIdno("1003600123456");
// MPowerCode: "MPower-12345678" -> "MPower-****5678"
var maskedMPowerCode = PiiMaskingService.MaskMPowerCode("MPower-12345678");
}
}Device Information
Automatically captured device and browser information included with error reports for diagnostics.
public class DeviceInfo
{
public string? Browser { get; set; }
public string? BrowserVersion { get; set; }
public string? OperatingSystem { get; set; }
public string? DeviceType { get; set; } // Desktop, Mobile, Tablet
public string? ScreenResolution { get; set; }
public string? TimeZone { get; set; }
public string? Language { get; set; }
public bool OnlineStatus { get; set; }
public bool CookiesEnabled { get; set; }
}
// Device info is automatically captured via JavaScript interop
// and included in FodErrorReport.Device propertyHTTP Interceptor
Automatically intercepts HTTP responses with configured status codes and creates error reports via ErrorHandlingHttpMessageHandler.
// Register HttpClient with error handling in Program.cs
builder.Services.AddHttpClient("DemoApi", client =>
{
client.BaseAddress = new Uri("https://api.example.com/");
}).WithErrorHandling();
// Usage - errors are automatically intercepted
@inject IHttpClientFactory HttpClientFactory
@code {
private async Task CallApi()
{
var client = HttpClientFactory.CreateClient("DemoApi");
var response = await client.GetAsync("/api/data");
// If status code is in InterceptStatusCodes,
// ErrorHandlingHttpMessageHandler creates FodErrorReport automatically
}
}Retry Logic
Exponential backoff retry strategy with configurable attempts and delays.
public class RetryPolicy
{
public int MaxRetries { get; set; } = 3;
public int BaseDelayMs { get; set; } = 100;
public async Task<T> ExecuteAsync<T>(
Func<Task<T>> operation,
CancellationToken ct = default)
{
for (int attempt = 1; attempt <= MaxRetries; attempt++)
{
try
{
return await operation();
}
catch when (attempt < MaxRetries)
{
int delayMs = (int)Math.Pow(2, attempt - 1) * BaseDelayMs;
await Task.Delay(delayMs, ct);
}
}
throw new InvalidOperationException("Max retries exceeded");
}
}Circuit Breaker
Automatic failure protection preventing cascading failures across services.
Circuit is closed. All requests pass through normally.
public enum CircuitState { Closed = 0, Open = 1, HalfOpen = 2 }
public class CircuitBreaker
{
public CircuitState State { get; private set; } = CircuitState.Closed;
public int FailureThreshold { get; set; } = 3;
private int _failureCount;
public async Task<T> ExecuteAsync<T>(Func<Task<T>> operation)
{
if (State == CircuitState.Open)
throw new InvalidOperationException("Circuit is open");
try
{
return await operation();
}
catch
{
_failureCount++;
if (_failureCount >= FailureThreshold)
State = CircuitState.Open;
throw;
}
}
public void Reset()
{
_failureCount = 0;
State = CircuitState.Closed;
}
}OnErrorOccurred Event
Subscribe to global error events fired by IFodErrorHandlerService when errors are handled.
Error Report Structure
Full FodErrorReport with all 20+ properties including context, device info, and metadata.
Configuration Options
Current FodErrorHandlerConfiguration values. Toggle options to see effect on behavior.
- MaxRetryAttempts
3- InitialRetryDelaySeconds
2- MaxRetryDelaySeconds
30- BackoffMultiplier
2- UseJitter
True- IncludeSensitiveData
False- CircuitBreakerFailureThreshold
5- CircuitBreakerOpenDurationMinutes
2- EnableLocalStorageFallback
True- ErrorRetentionDays
90- InterceptStatusCodes
500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511
Requestor Context
Extract requestor context with automatic PII masking via IFodContextExtractor<FodRequestorContext>.
Beneficiary Context
Extract beneficiary context with automatic PII masking via IFodContextExtractor<FodBeneficiaryContext>.
Session Context
Extract session context including wizard step tracking via FodSessionContextExtractor.
Error Log Service
InMemoryErrorLogService for storing, retrieving, and managing error reports with GDPR deletion support.
Error Report Queue
Channel-based bounded queue for error report processing with configurable capacity.
MNotify Integration
Send error reports to the MNotify notification platform. Uses MockMNotifyService in development.
Sensitive Data Detector
Detect and mask PII patterns in arbitrary text using regex-based FodSensitiveDataDetector.
Error Retention
GDPR-compliant error retention with configurable expiration policy via FodErrorRetentionService.
- Retention Policy
90 days- Expiration Date (from now)
2026-08-18
User Action Tracker
Track user actions with a rolling buffer (max 20) via UserActionTracker for error context.
Error Message Service
Localized error titles and messages for HTTP status codes via IFodErrorMessageService.
Global Exception Handler
GlobalExceptionHandler catches unobserved task exceptions and AppDomain unhandled exceptions.
GlobalExceptionHandler.Initialize() was called in Program.cs to register exception handlers.
API Endpoints
Available REST API endpoints for error reporting and management.
| Endpoint | Method | Description |
|---|---|---|
api/fod/errors |
POST | Submit a new error report |
api/fod/errors/{"{id}"} |
GET | Retrieve error report by ID |
api/fod/errors/recent |
GET | Get list of recent error reports |
api/fod/errors/device-info |
GET | Get current device information |
api/fod/errors/user/{"{userId}"} |
DELETE | GDPR deletion of user error data |
API Reference
Configuration options for error handling service.
