I am trying to configure my middleware pipeline to use 2 different exception handlers to handle the same exception. For example, I'm trying to have both my custom handler and in-built DeveloperExceptionPageMiddleware as follows:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.ConfigureCustomExceptionHandler();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.ConfigureCustomExceptionHandler();
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvcWithDefaultRoute();
}
My objective is to have the custom handler do its own thing (logging, telemetry, etc), and then pass on (next()) to the other in-built handler which displays a page. My custom handler looks like this:
public static class ExceptionMiddlewareExtensions
{
public static void ConfigureCustomExceptionHandler(this IApplicationBuilder app)
{
app.UseExceptionHandler(appError =>
{
appError.Use(async (context, next) =>
{
var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
if (contextFeature != null)
{
//log error / do custom stuff
await next();
}
});
});
}
}
I cannot get CustomExceptionHandler to pass on processing to the next middleware. I get the following page instead:
404 error:
I tried switching around the order, but then the developer exception page takes over and the custom exception handler is not called.
Is what I'm trying to do possible at all?
Update:
The solution was to take Simonare's original suggestion and re-throw the exception in the
Invoke
method. I also had to remove any type of response-meddling by replacing the following inHandleExceptionAsync
method:
context.Response.ContentType = "application/json"; context.Response.StatusCode = (int)code; return context.Response.WriteAsync(result);
with:
return Task.CompletedTask;
By handling multiple exceptions, a program can respond to different exceptions without terminating it. In Python, try-except blocks can be used to catch and respond to one or multiple exceptions. In cases where a process raises more than one possible exception, they can all be handled using a single except clause.
I have multiple classes annotated with @ControllerAdvice , each with an @ExceptionHandler method in. One handles Exception with the intention that if no more specific handler is found, this should be used.
Starting from Java 7.0, it is possible for a single catch block to catch multiple exceptions by separating each with | (pipe symbol) in the catch block. Catching multiple exceptions in a single catch block reduces code duplication and increases efficiency.
Python Multiple Exception in one Except You can also have one except block handle multiple exceptions. To do this, use parentheses. Without that, the interpreter will return a syntax error.
Java allows you to catch multiple type exceptions in a single catch block. It was introduced in Java 7 and helps to optimize code. You can use vertical bar (|) to separate multiple exceptions in catch block.
There are mainly two types of exceptions: checked and unchecked.
Instead of calling two different Exception Handling Middleware, you may consider to add logging under your Home/Error
[AllowAnonymous]
public IActionResult Error()
{
//log your error here
return View(new ErrorViewModel
{ RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
alternatively, you can use custom Expception Handling Middleware
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context, IHostingEnvironment env)
{
try
{
await _next(context);
}
catch (Exception ex)
{
if (!context.Response.HasStarted)
await HandleExceptionAsync(context, ex, env);
throw;
}
}
private Task HandleExceptionAsync(HttpContext context, Exception exception, IHostingEnvironment env)
{
var code = HttpStatusCode.InternalServerError; // 500 if unexpected
var message = exception.Message;
switch (exception)
{
case NotImplementedException _:
code = HttpStatusCode.NotImplemented;
break;
//other custom exception types can be used here
case CustomApplicationException cae: //example
code = HttpStatusCode.BadRequest;
break;
}
Log.Write(code == HttpStatusCode.InternalServerError ? LogEventLevel.Error : LogEventLevel.Warning, exception, "Exception Occured. HttpStatusCode={0}", code);
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)code;
return Task.Completed;
}
}
and Simply Register it inside IApplicationBuilder Method
public void Configure(IApplicationBuilder app)
{
app.UseMiddleware<ErrorHandlingMiddleware>();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With