-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Creating GlobalExceptionHandler for handling errors throughout projec…
…t with custom Exception
- Loading branch information
Showing
7 changed files
with
154 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace EWallet.Infrastructure.ExceptionHandler; | ||
|
||
public class AppException : Exception | ||
{ | ||
// TODO : complete | ||
} |
36 changes: 36 additions & 0 deletions
36
EWallet.Infrastructure/ExceptionHandler/ExceptionExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
namespace EWallet.Infrastructure.ExceptionHandler; | ||
|
||
public static class ExceptionExtensions | ||
{ | ||
private const string ErrorCodeKey = "ErrorCode"; | ||
|
||
/// <summary> | ||
/// Adds or updates the error code for the exception. | ||
/// </summary> | ||
/// <param name="exception">The exception to enrich.</param> | ||
/// <param name="errorCode">The error code to add. Defaults to "GenericError".</param> | ||
public static void AddErrorCode(this Exception exception, string errorCode = "GenericError") | ||
{ | ||
if (exception == null) | ||
{ | ||
throw new ArgumentNullException(nameof(exception), "Exception cannot be null."); | ||
} | ||
|
||
exception.Data[ErrorCodeKey] = errorCode; | ||
} | ||
|
||
/// <summary> | ||
/// Retrieves the error code from the exception, if it exists. | ||
/// </summary> | ||
/// <param name="exception">The exception to retrieve the error code from.</param> | ||
/// <returns>The error code, or null if none exists.</returns> | ||
public static string? GetErrorCode(this Exception exception) | ||
{ | ||
if (exception == null) | ||
{ | ||
throw new ArgumentNullException(nameof(exception), "Exception cannot be null."); | ||
} | ||
|
||
return exception.Data.Contains(ErrorCodeKey) ? exception.Data[ErrorCodeKey]?.ToString() : null; | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
EWallet.Infrastructure/ExceptionHandler/GlobalExceptionHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
using System.Diagnostics; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using Microsoft.AspNetCore.Diagnostics; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.WebUtilities; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace EWallet.Infrastructure.ExceptionHandler; | ||
|
||
public class GlobalExceptionHandler(IHostEnvironment env, ILogger<GlobalExceptionHandler> logger) : IExceptionHandler | ||
{ | ||
private const string UnhandledExceptionMsg = "An unhandled exception has occurred while executing the request."; | ||
|
||
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web) | ||
{ | ||
Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) } | ||
}; | ||
|
||
|
||
public async ValueTask<bool> TryHandleAsync(HttpContext context, Exception exception, | ||
CancellationToken cancellationToken) | ||
{ | ||
exception.AddErrorCode(); | ||
logger.LogError(exception, exception is AppException ? exception.Message : UnhandledExceptionMsg); | ||
|
||
var problemDetails = CreateProblemDetails(context, exception); | ||
var json = ToJson(problemDetails); | ||
|
||
const string contentType = "application/problem+json"; | ||
context.Response.ContentType = contentType; | ||
await context.Response.WriteAsync(json, cancellationToken); | ||
|
||
return true; | ||
} | ||
|
||
private ProblemDetails CreateProblemDetails(in HttpContext context, in Exception exception) | ||
{ | ||
var errorCode = exception.GetErrorCode(); | ||
var statusCode = context.Response.StatusCode; | ||
var reasonPhrase = ReasonPhrases.GetReasonPhrase(statusCode); | ||
if (string.IsNullOrEmpty(reasonPhrase)) | ||
{ | ||
reasonPhrase = UnhandledExceptionMsg; | ||
} | ||
|
||
var problemDetails = new ProblemDetails | ||
{ | ||
Status = statusCode, | ||
Title = reasonPhrase, | ||
Extensions = | ||
{ | ||
[nameof(errorCode)] = errorCode | ||
} | ||
}; | ||
|
||
if (!env.IsDevelopment()) | ||
{ | ||
return problemDetails; | ||
} | ||
|
||
problemDetails.Detail = exception.ToString(); | ||
problemDetails.Extensions["traceId"] = Activity.Current?.Id; | ||
problemDetails.Extensions["requestId"] = context.TraceIdentifier; | ||
problemDetails.Extensions["data"] = exception.Data; | ||
|
||
return problemDetails; | ||
} | ||
|
||
private string ToJson(in ProblemDetails problemDetails) | ||
{ | ||
try | ||
{ | ||
return JsonSerializer.Serialize(problemDetails, SerializerOptions); | ||
} | ||
catch (Exception ex) | ||
{ | ||
const string msg = "An exception has occurred while serializing error to JSON"; | ||
logger.LogError(ex, msg); | ||
} | ||
|
||
return string.Empty; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters