Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle internal server errors #170

Merged
merged 10 commits into from
Oct 5, 2023
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -672,3 +672,4 @@ fabric.properties
**/wwwroot/bundled
ocelot.json
/src/2-Services/Identity/Api/Identity.Api/keys
/src/6-Docker/mssqldata/Entropy.bin
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace TaskoMask.BuildingBlocks.Application.Behaviors
{
public static class BehaviorsExtensions
public static class BehaviorExtensions
{


Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using TaskoMask.BuildingBlocks.Domain.Exceptions;
using TaskoMask.BuildingBlocks.Contracts.Exceptions;

namespace TaskoMask.BuildingBlocks.Application.Exceptions
{

/// <summary>
///
/// </summary>
public class ApplicationException : DomainException
public class ApplicationException : ManagedException
{
#region Ctors

Expand Down
38 changes: 38 additions & 0 deletions src/1-BuildingBlocks/Application/Exceptions/ExceptionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using MediatR.Pipeline;
using Microsoft.Extensions.DependencyInjection;

namespace TaskoMask.BuildingBlocks.Application.Exceptions
{
public static class ExceptionExtensions
{

/// <summary>
///
/// </summary>
public static void AddApplicationExceptionHandlers(this IServiceCollection services)
{
services.AddManagedExceptionsHandler();
services.AddUnmanagedExceptionsHandler();
}



/// <summary>
///
/// </summary>
private static void AddManagedExceptionsHandler(this IServiceCollection services)
{
services.AddScoped(typeof(IRequestExceptionHandler<,,>), typeof(ManagedExceptionHandler<,,>));
}


/// <summary>
///
/// </summary>
private static void AddUnmanagedExceptionsHandler(this IServiceCollection services)
{
services.AddScoped(typeof(IRequestExceptionHandler<,,>), typeof(UnmanagedExceptionHandler<,,>));
}

}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
using TaskoMask.BuildingBlocks.Application.Notifications;
using MediatR;
using MediatR.Pipeline;
using System.Threading;
using System.Threading.Tasks;
using TaskoMask.BuildingBlocks.Domain.Exceptions;
using Microsoft.Extensions.Logging;
using TaskoMask.BuildingBlocks.Contracts.Exceptions;
using System.Text.Json;

namespace TaskoMask.BuildingBlocks.Application.Exceptions
{
/// <summary>
///
/// Handle all managed exceptions (DomainException,ApplicationException,ValidationException)
/// </summary>
public class ApplicationExceptionsHandler<TRequest, TResponse, TException>
: IRequestExceptionHandler<TRequest, TResponse, TException> where TException : DomainException
public class ManagedExceptionHandler<TRequest, TResponse, TException>
: IRequestExceptionHandler<TRequest, TResponse, TException> where TException : ManagedException
{
#region Fields


private readonly INotificationHandler _notifications;

private readonly ILogger<ManagedExceptionHandler<TRequest, TResponse, TException>> _logger;

#endregion


#region Ctors


public ApplicationExceptionsHandler(INotificationHandler notifications)
public ManagedExceptionHandler(INotificationHandler notifications, ILogger<ManagedExceptionHandler<TRequest, TResponse, TException>> logger)
{
_notifications = notifications;
this._logger = logger;
}


#endregion


#region Handler


Expand All @@ -45,25 +45,11 @@ public Task Handle(TRequest request, TException exception, RequestExceptionHandl
{
var exceptionType = exception.GetType();

//notification exception error message if exist
//notify exception message if any
if (!string.IsNullOrEmpty(exception.Message))
_notifications.Add(exceptionType.Name, exception.Message);


if (exceptionType == typeof(ApplicationException))
{
//log ApplicationException ...
}

else if (exceptionType == typeof(ValidationException))
{
//log ValidationException ...
}

else if (exceptionType == typeof(DomainException))
{
//log DomainException ...
}
_logger.LogWarning(exception, $"request : {JsonSerializer.Serialize(request)}");

state.SetHandled(default);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using TaskoMask.BuildingBlocks.Application.Notifications;
using MediatR.Pipeline;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using System;
using System.Text.Json;

namespace TaskoMask.BuildingBlocks.Application.Exceptions
{
/// <summary>
/// Handle all unmanaged exceptions
/// </summary>
public class UnmanagedExceptionHandler<TRequest, TResponse, TException>
: IRequestExceptionHandler<TRequest, TResponse, TException> where TException : Exception
{
#region Fields


private readonly INotificationHandler _notifications;
private readonly ILogger<UnmanagedExceptionHandler<TRequest, TResponse, TException>> _logger;

#endregion

#region Ctors


public UnmanagedExceptionHandler(INotificationHandler notifications, ILogger<UnmanagedExceptionHandler<TRequest, TResponse, TException>> logger)
{
_notifications = notifications;
this._logger = logger;
}


#endregion

#region Handler



/// <summary>
///
/// </summary>
public Task Handle(TRequest request, TException exception, RequestExceptionHandlerState<TResponse> state, CancellationToken cancellationToken)
{
_notifications.Add("Unknown Exception", "Unknown exception happened");

_logger.LogError(exception, $"request : {JsonSerializer.Serialize(request)}");

state.SetHandled(default);

return Task.CompletedTask;
}


#endregion
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using TaskoMask.BuildingBlocks.Domain.Exceptions;
using TaskoMask.BuildingBlocks.Contracts.Exceptions;

namespace TaskoMask.BuildingBlocks.Application.Exceptions
{

/// <summary>
///
/// </summary>
public class ValidationException : DomainException
public class ValidationException : ManagedException
{
#region Ctors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static void AddBuildingBlocksApplication(this IServiceCollection services
if (services == null)
throw new ArgumentNullException(nameof(services));

services.AddApplicationExceptionsHandler();
services.AddApplicationExceptionHandlers();
services.AddApplicationBehaviors(validatorAssemblyMarkerType);
services.AddDomainNotificationHandler();
}
Expand Down
14 changes: 14 additions & 0 deletions src/1-BuildingBlocks/Contracts/Exceptions/DomainException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
namespace TaskoMask.BuildingBlocks.Contracts.Exceptions
{
/// <summary>
///
/// </summary>
public class ManagedException : Exception
{
public ManagedException(string message): base(message)
{
}

}
}
5 changes: 3 additions & 2 deletions src/1-BuildingBlocks/Domain/Exceptions/DomainException.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System;
using TaskoMask.BuildingBlocks.Contracts.Exceptions;

namespace TaskoMask.BuildingBlocks.Domain.Exceptions
{
/// <summary>
///
/// </summary>
public class DomainException : Exception
public class DomainException : ManagedException
{
public DomainException(string message): base(message)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using TaskoMask.BuildingBlocks.Web.MVC.Exceptions;

namespace TaskoMask.BuildingBlocks.Web.Grpc.Configuration
{

/// <summary>
///
/// </summary>
public static class GrpcConfiguration
{


/// <summary>
///
/// </summary>
public static void AddGrpcPreConfigured(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));

services.AddGrpc(options =>
{
options.Interceptors.Add<GrpcGlobalExceptionHandler>();
});
}


}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MonoApi.Services.Afrr.Activations.Api.Helpers;
using TaskoMask.BuildingBlocks.Web.MVC.Configuration.Jwt;
using TaskoMask.BuildingBlocks.Web.MVC.Configuration.Swagger;
using TaskoMask.BuildingBlocks.Web.MVC.Services.AuthenticatedUser;
Expand Down Expand Up @@ -55,6 +55,9 @@ public static void UseWebApiPreConfigured(this IApplicationBuilder app, IWebHost
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();

app.UseGlobalExceptionHandler();


app.UseSwaggerPreConfigured();

app.UseHttpsRedirection();
Expand All @@ -76,12 +79,20 @@ public static void UseWebApiPreConfigured(this IApplicationBuilder app, IWebHost
/// <summary>
/// Prevent auto validate on model binding
/// </summary>
private static IMvcBuilder WithPreventAutoValidation(this IMvcBuilder builder)
private static void WithPreventAutoValidation(this IMvcBuilder builder)
{
return builder.ConfigureApiBehaviorOptions(options =>
builder.ConfigureApiBehaviorOptions(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
}

/// <summary>
///
/// </summary>
private static void UseGlobalExceptionHandler(this IApplicationBuilder app)
{
app.UseMiddleware<HttpGlobalExceptionHandler>();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
using Grpc.Core;
using Grpc.Core.Interceptors;
using Microsoft.Extensions.Logging;

namespace TaskoMask.BuildingBlocks.Web.MVC.Exceptions
{
/// <summary>
/// Global exception handler for gRPC services
/// </summary>
public class GrpcExceptionInterceptor : Interceptor
public class GrpcGlobalExceptionHandler : Interceptor
{
private readonly ILogger _logger;

public GrpcGlobalExceptionHandler(ILogger logger)
{
this._logger = logger;
}

public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
TRequest request,
ServerCallContext context,
Expand All @@ -19,6 +27,8 @@ public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
}
catch (Exception exception)
{
_logger.LogError(exception, exception.Message);

throw new RpcException(new Status(StatusCode.Cancelled, exception.Message));
}
}
Expand Down
Loading
Loading