Catalin
Catalin

Reputation: 11721

Get exception in Middleware

I want to create an AspNetCore Middleware (old IHttpModule), which should capture exceptions (later on save them or something similar)

However, i don't know how to capture the Exception inside Middleware, although the HttpStatusCode is 500

Here is what i have:

// Middleware
internal class ExceptionMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next.Invoke(context);
        }
        catch (Exception ex)
        {
            // never gets here
        }

        // 500
        HttpStatusCode statusCode = (HttpStatusCode)context.Response.StatusCode;

        // how to get error message?
    }
}

// Middleware Extension method
public static class ExceptionMiddlewareExtensions
{
    public static IApplicationBuilder UseExceptionMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<ExceptionMiddleware>();
    }
}

// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseExceptionMiddleware();

    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

I trigger the exception like this:

public IActionResult Index()
{
    var test = 0;
    var a = 100 / test;

    return View();
}

Upvotes: 3

Views: 7238

Answers (2)

Konrad
Konrad

Reputation: 7198

You're re-inventing the wheel.

How to do it right without your own middleware:

You can get error details using built-in ExceptionHandlerMiddleware (app.UseExceptionHandler) ASP.NET Core gives you, this is not documented but it should be.

When exception occurs this middleware sets IExceptionHandlerFeature (with exception that occured) and IExceptionHandlerPathFeature (with derives from IExceptionHandlerFeature) on HttpContext.

So you can access your exception details through HttpContext.Features:

Assuming you're invoking this inside your /Home/Error controller's action you can access it like:

var exHandlerFeature = HttpContext.Features.Get<IExceptionHandlerFeature>();
var exception = exHandlerFeature.Error;

Also see this answer and question about Request Features

There's a blog post about this too if you are interested

Upvotes: 7

Set
Set

Reputation: 49769

You correctly use try-catch in middleware.

But your problem is that you also register the ExceptionHandler middleware (app.UseExceptionHandler). This middleware catches all unhandled exceptions and set 500 status code if could handle it.


As a possible solution consider to swap the order of middlewares, so your middleware will be the first one that catches the exceptions occurred further in the pipeline:

app.UseExceptionHandler("/Home/Error");
app.UseExceptionMiddleware();

Upvotes: 7

Related Questions