Skip to content

Commit

Permalink
improve exception handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
ysmoradi committed Nov 14, 2024
1 parent 7866259 commit 5bce2ce
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@

namespace Boilerplate.Client.Core.Services;

public abstract partial class ExceptionHandlerBase : IExceptionHandler
public abstract partial class ClientExceptionHandlerBase : SharedExceptionHandler, IExceptionHandler
{
[AutoInject] protected Bit.Butil.Console Console = default!;
[AutoInject] protected ITelemetryContext TelemetryContext = default!;
[AutoInject] protected ILogger<ExceptionHandlerBase> Logger = default!;
[AutoInject] protected ILogger<ClientExceptionHandlerBase> Logger = default!;
[AutoInject] protected readonly MessageBoxService MessageBoxService = default!;
[AutoInject] protected readonly IStringLocalizer<AppStrings> Localizer = default!;

public void Handle(Exception exception,
Dictionary<string, object?>? parameters = null,
Expand All @@ -35,14 +34,7 @@ protected virtual void Handle(Exception exception, Dictionary<string, object> pa

using (var scope = Logger.BeginScope(parameters.ToDictionary(i => i.Key, i => i.Value ?? string.Empty)))
{
var exceptionMessageToLog = exception.Message;
var innerException = exception.InnerException;

while (innerException is not null)
{
exceptionMessageToLog += $"{Environment.NewLine}{innerException.Message}";
innerException = innerException.InnerException;
}
var exceptionMessageToLog = GetExceptionMessageToLog(exception);

if (exception is KnownException)
{
Expand All @@ -54,8 +46,7 @@ protected virtual void Handle(Exception exception, Dictionary<string, object> pa
}
}

string exceptionMessageToShow = (exception as KnownException)?.Message ??
(isDevEnv ? exception.ToString() : Localizer[nameof(AppStrings.UnknownException)]);
string exceptionMessageToShow = GetExceptionMessageToShow(exception);

MessageBoxService.Show(exceptionMessageToShow, Localizer[nameof(AppStrings.Error)]);

Expand All @@ -64,29 +55,4 @@ protected virtual void Handle(Exception exception, Dictionary<string, object> pa
Debugger.Break();
}
}

protected Exception UnWrapException(Exception exception)
{
if (exception is AggregateException aggregateException)
{
return aggregateException.Flatten().InnerException ?? aggregateException;
}
else if (exception is TargetInvocationException)
{
return exception.InnerException ?? exception;
}

return exception;
}

protected bool IgnoreException(Exception exception)
{
if (exception is KnownException)
return false;

return exception is TaskCanceledException ||
exception is OperationCanceledException ||
exception is TimeoutException ||
(exception.InnerException is not null && IgnoreException(exception.InnerException));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Boilerplate.Client.Maui.Services;
/// Employing Microsoft.Extensions.Logging implementations (like Sentry.Extensions.Logging) will result in
/// automatic exception logging due to the logger.LogError method call within the ExceptionHandlerBase class.
/// </summary>
public partial class MauiExceptionHandler : ExceptionHandlerBase
public partial class MauiExceptionHandler : ClientExceptionHandlerBase
{
protected override void Handle(Exception exception, Dictionary<string, object> parameters)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Boilerplate.Client.Web.Services;

public partial class WebExceptionHandler : ExceptionHandlerBase
public partial class WebExceptionHandler : ClientExceptionHandlerBase
{
protected override void Handle(Exception exception, Dictionary<string, object> parameters)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// Employing Microsoft.Extensions.Logging implementations (like Sentry.Extensions.Logging) will result in
/// automatic exception logging due to the logger.LogError method call within the ExceptionHandlerBase class.
/// </summary>
public partial class WindowsExceptionHandler : ExceptionHandlerBase
public partial class WindowsExceptionHandler : ClientExceptionHandlerBase
{
protected override void Handle(Exception exception, Dictionary<string, object> parameters)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
using System.Net;
using System.Reflection;
using System.Diagnostics;
using Microsoft.Net.Http.Headers;
using Microsoft.AspNetCore.Diagnostics;

namespace Boilerplate.Server.Api.Services;

public partial class ServerExceptionHandler : IExceptionHandler
public partial class ServerExceptionHandler : SharedExceptionHandler, IExceptionHandler
{
[AutoInject] private IWebHostEnvironment webHostEnvironment = default!;
[AutoInject] private IStringLocalizer<AppStrings> localizer = default!;
[AutoInject] private JsonSerializerOptions jsonSerializerOptions = default!;

public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception e, CancellationToken cancellationToken)
Expand All @@ -22,13 +20,13 @@ public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception e

// The details of all of the exceptions are returned only in dev mode. in any other modes like production, only the details of the known exceptions are returned.
var key = knownException?.Key ?? nameof(UnknownException);
var message = knownException?.Message ?? (webHostEnvironment.IsDevelopment() ? exception.Message : localizer[nameof(UnknownException)]);
var message = GetExceptionMessageToShow(exception);

var statusCode = (int)(exception is RestException restExp ? restExp.StatusCode : HttpStatusCode.InternalServerError);

if (exception is KnownException && message == key)
{
message = localizer[message];
message = Localizer[message];
}

var restExceptionPayload = new RestErrorInfo
Expand All @@ -49,18 +47,4 @@ public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception e

return true;
}

private Exception UnWrapException(Exception exception)
{
if (exception is AggregateException aggregateException)
{
return aggregateException.Flatten().InnerException ?? aggregateException;
}
else if (exception is TargetInvocationException)
{
return exception.InnerException ?? exception;
}

return exception;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System.Reflection;

namespace Boilerplate.Shared.Services;

public partial class SharedExceptionHandler
{
[AutoInject] protected IStringLocalizer<AppStrings> Localizer { get; set; } = default!;

protected string GetExceptionMessageToShow(Exception exception)
{
if (exception is KnownException)
return exception.Message;

if (AppEnvironment.IsDev())
return exception.ToString();

return Localizer[nameof(AppStrings.UnknownException)];
}

protected string GetExceptionMessageToLog(Exception exception)
{
var exceptionMessageToLog = exception.Message;
var innerException = exception.InnerException;

while (innerException is not null)
{
exceptionMessageToLog += $"{Environment.NewLine}{innerException.Message}";
innerException = innerException.InnerException;
}

return exceptionMessageToLog;
}

protected Exception UnWrapException(Exception exception)
{
if (exception is AggregateException aggregateException)
{
return aggregateException.Flatten().InnerException ?? aggregateException;
}
else if (exception is TargetInvocationException)
{
return exception.InnerException ?? exception;
}

return exception;
}

protected bool IgnoreException(Exception exception)
{
if (exception is KnownException)
return false;

return exception is TaskCanceledException ||
exception is OperationCanceledException ||
exception is TimeoutException ||
(exception.InnerException is not null && IgnoreException(exception.InnerException));
}
}

0 comments on commit 5bce2ce

Please sign in to comment.