From 53e763d859e28707eb038ab980dcc03320768a6f Mon Sep 17 00:00:00 2001 From: Tom Dykstra Date: Fri, 30 Jun 2023 15:15:39 -0700 Subject: [PATCH 1/3] Document IExceptionHandler (#29674) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Günther Foidl --- aspnetcore/fundamentals/error-handling.md | 26 ++++++++++++++++++- .../CustomExceptionHandler.cs | 20 +++++++++----- .../8.x/ErrorHandlingSample/Program.cs | 8 +++--- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/aspnetcore/fundamentals/error-handling.md b/aspnetcore/fundamentals/error-handling.md index f4d14730c9f8..3108fc563e77 100644 --- a/aspnetcore/fundamentals/error-handling.md +++ b/aspnetcore/fundamentals/error-handling.md @@ -5,7 +5,7 @@ description: Discover how to handle errors in ASP.NET Core apps. monikerRange: '>= aspnetcore-3.1' ms.author: riande ms.custom: mvc -ms.date: 01/18/2023 +ms.date: 06/30/2023 uid: fundamentals/error-handling --- # Handle errors in ASP.NET Core @@ -91,6 +91,30 @@ The following code uses a lambda for exception handling: > [!WARNING] > Do **not** serve sensitive error information to clients. Serving errors is a security risk. +## IExceptionHandler + +[IExceptionHandler](https://source.dot.net/#Microsoft.AspNetCore.Diagnostics/ExceptionHandler/IExceptionHandler.cs,adae2915ad0c6dc5) is an interface that gives the developer a callback for handling known exceptions in a central location. + +`IExceptionHandler` implementations are registered by calling [`IServiceCollection.AddExceptionHandler`](https://source.dot.net/#Microsoft.AspNetCore.Diagnostics/ExceptionHandler/ExceptionHandlerServiceCollectionExtensions.cs,e74aac24e3e2cbc9). Multiple implementations can be added, and they're called in the order registered. If an exception handler handles a request, it can return `true` to stop processing. If an exception isn't handled by any exception handler, then control falls back to the default behavior and options from the middleware. Different metrics and logs are emitted for handled versus unhandled exceptions. + +The following example shows an `IExceptionHandler` implementation: + +:::code language="csharp" source="~/fundamentals/error-handling/samples/8.x/ErrorHandlingSample/CustomExceptionHandler.cs"::: + +The following example shows how to register an `IExceptionHandler` implementation for dependency injection: + +:::code language="csharp" source="~/fundamentals/error-handling/samples/8.x/ErrorHandlingSample/Program.cs" id="snippet_RegisterIExceptionHandler" highlight="7"::: + +When the preceding code runs in the Development environment: + +* The `CustomExceptionHandler` is called first to handle an exception. +* After logging the exception, the `TryHandleException` method returns `false`, so the [developer exception page](#developer-exception-page) is shown. + +In other environments: + +* The `CustomExceptionHandler` is called first to handle an exception. +* After logging the exception, the `TryHandleException` method returns `false`, so the [`/Error` page](#exception-handler-page) is shown. + diff --git a/aspnetcore/fundamentals/error-handling/samples/8.x/ErrorHandlingSample/CustomExceptionHandler.cs b/aspnetcore/fundamentals/error-handling/samples/8.x/ErrorHandlingSample/CustomExceptionHandler.cs index 19632096f0bd..520502a6e036 100644 --- a/aspnetcore/fundamentals/error-handling/samples/8.x/ErrorHandlingSample/CustomExceptionHandler.cs +++ b/aspnetcore/fundamentals/error-handling/samples/8.x/ErrorHandlingSample/CustomExceptionHandler.cs @@ -1,19 +1,25 @@ -using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Diagnostics; namespace ErrorHandlingSample { public class CustomExceptionHandler : IExceptionHandler { - private ILogger logger; - public CustomExceptionHandler(ILogger logger){ + private readonly ILogger logger; + public CustomExceptionHandler(ILogger logger) + { this.logger = logger; } - public ValueTask TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken) + public ValueTask TryHandleAsync( + HttpContext httpContext, + Exception exception, + CancellationToken cancellationToken) { var exceptionMessage = exception.Message; - logger.LogError("Error Message: {exceptionMessage}", exceptionMessage); - logger.LogError("Time of occurrence {time}", DateTime.Now); - // returned false to continue with the default behavior + logger.LogError( + "Error Message: {exceptionMessage}, Time of occurrence {time}", + exceptionMessage, DateTime.UtcNow); + // Return false to continue with the default behavior + // - or - return true to signal that this exception is handled return ValueTask.FromResult(false); } } diff --git a/aspnetcore/fundamentals/error-handling/samples/8.x/ErrorHandlingSample/Program.cs b/aspnetcore/fundamentals/error-handling/samples/8.x/ErrorHandlingSample/Program.cs index f028c05b3612..b544d7f97b78 100644 --- a/aspnetcore/fundamentals/error-handling/samples/8.x/ErrorHandlingSample/Program.cs +++ b/aspnetcore/fundamentals/error-handling/samples/8.x/ErrorHandlingSample/Program.cs @@ -1,4 +1,4 @@ -// +// using ErrorHandlingSample; var builder = WebApplication.CreateBuilder(args); @@ -6,9 +6,7 @@ builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddRazorPages(); builder.Services.AddExceptionHandler(); -// -// var app = builder.Build(); if (!app.Environment.IsDevelopment()) @@ -16,7 +14,9 @@ app.UseExceptionHandler("/Error"); app.UseHsts(); } -// + +// Remaining Program.cs code omitted for brevity +// app.UseHttpsRedirection(); app.UseStaticFiles(); From 3d3695115ea25b4fb7c43f2c109751402d876510 Mon Sep 17 00:00:00 2001 From: Tom Dykstra Date: Fri, 30 Jun 2023 15:26:08 -0700 Subject: [PATCH 2/3] Iexceptionhandler3 (#29691) * Add IExceptionHandler to WN * Update aspnetcore-8.0.md --- aspnetcore/release-notes/aspnetcore-8.0.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/aspnetcore/release-notes/aspnetcore-8.0.md b/aspnetcore/release-notes/aspnetcore-8.0.md index c33d00344de0..27c76dc3bb49 100644 --- a/aspnetcore/release-notes/aspnetcore-8.0.md +++ b/aspnetcore/release-notes/aspnetcore-8.0.md @@ -4,7 +4,7 @@ author: rick-anderson description: Learn about the new features in ASP.NET Core 8.0. ms.author: riande ms.custom: mvc -ms.date: 06/27/2023 +ms.date: 06/30/2023 uid: aspnetcore-8 --- # What's new in ASP.NET Core 8.0 @@ -468,6 +468,14 @@ Metrics offers a number of improvements compared to existing event counters: Metrics have been added for ASP.NET Core hosting, Kestrel, and SignalR. For more information, see [System.Diagnostics.Metrics](/dotnet/core/diagnostics/compare-metric-apis#systemdiagnosticsmetrics). +### IExceptionHandler + +[IExceptionHandler](https://source.dot.net/#Microsoft.AspNetCore.Diagnostics/ExceptionHandler/IExceptionHandler.cs,adae2915ad0c6dc5) is a new interface that gives the developer a callback for handling known exceptions in a central location. + +`IExceptionHandler` implementations are registered by calling [`IServiceCollection.AddExceptionHandler`](https://source.dot.net/#Microsoft.AspNetCore.Diagnostics/ExceptionHandler/ExceptionHandlerServiceCollectionExtensions.cs,e74aac24e3e2cbc9). Multiple implementations can be added, and they're called in the order registered. If an exception handler handles a request, it can return `true` to stop processing. If an exception isn't handled by any exception handler, then control falls back to the default behavior and options from the middleware. + +For more information, see [IExceptionHandler](xref:fundamentals/error-handling#iexceptionhandler). +