Lately, I have been trying to implement a strategy for dealing with Exceptions in my C# ASP.NET CORE application with no success. This strategy is structured in two parts:
The first is to have a MiddleWare solely responsible for dealing with a given custom type of Exception that my application may throw. If one is detected, this middleware should be capable of redirecting it back into a specific controller’s action that knows how to handle this type of exception.
The second part is the Controller that handles this exception sent by the middleware. Ideally, I would like to retrieve the exception (within my controller’s endpoint) by means of the “HttpContext.Features.Get” method. Nevertheless, despite my attempts, the returned feature is returned as null; thus, no exception is retrieved by my controller (see types definition from the code below).
I would like to point out that this question arose from a deep search of alternative strategies found online (like the ones found in here, and here), and from the Microsoft’s documentation itself.
I thank you for your time. Any help is appreciated.
Types definition:
Controller’s definition:
public class ExceptionManagerController : AppController
{
public ExceptionManagerController() : base()
{
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public async Task<IActionResult> Index()
{
var exceptionHandlerPathFeature = HttpContext.Features.Get<IExceptionHttpContextFeature>();
var excecao = exceptionHandlerPathFeature?.Exception;
if ( excecao == null)
{
return RedirectToAction("Index", "Home");
}
else
{
var vm = new GlobalExceptionVM(excecao);
return View(vm);
}
}
}
HttpContext.Feature’s custom Interface definition:
public interface IExceptionHttpContextFeature
{
Exception Exception { get; }
}
Custom Interface’s implementation definition:
public class ExceptionHttpContextFeature: IExceptionHttpContextFeature
{
public Exception Exception {get;}
public ExceptionHttpContextFeature()
{
}
public ExceptionHttpContextFeature(Exception exception)
{
this.Exception = exception;
}
}
Middleware defintion:
public class GlobalExceptionHandler : IExceptionHandler
{
private ILogger<GlobalExceptionHandler> Logger;
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
{
Logger = logger;
}
public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
{
if ( exception != null)
{
var originalBodyStream = httpContext.Response.Body;
Logger.LogError($"Erro na solicitação do usuário {httpContext.User.Identity.Name}. Error Message: {exception.Message}, Time of occurrence {DateTime.UtcNow}");
httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
httpContext.Response.Redirect("/GestorDeExcecoes/Index");
httpContext.Features.Set<IExceptionHttpContextFeature>(new ExceptionHttpContextFeature(exception));
}
return true;
}
}