MikeT
MikeT

Reputation: 2663

IApplicationBuilder.UseExceptionHandler overload not using Error page

I'm using the overload IApplicationBuilder.UseExceptionHandler(Action<IApplicationBuilder> configure) so that I can add an entry into my database for any unhandled exceptions.

So a new ASP.NET Core 2.1 web app comes with this in Startup.Configure:

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

where I've switched app.UseExceptionHandler("/Home/Error"); out with

//app.UseExceptionHandler("/Home/Error");
app.UseExceptionHandler(configure =>
{
    configure.Run(async context =>
    {
        UncaughtExceptionHandler uncaughtExceptionHandler = new UncaughtExceptionHandler();

        await uncaughtExceptionHandler.LogUnhandledException(
            context.Features.Get<IExceptionHandlerFeature>().Error,
            Configuration.GetConnectionString("RemoteConnection"));
    });
    //configure.UseExceptionHandler("/Home/Error");
});

If I uncomment app.UseExceptionHandler("/Home/Error"); then the Error page gets hit, but the exception doesn't get added to my database's Errors table. Doesn't matter if I place the line before or after the UseExceptionHandler overload.

The commented out configure.UseExceptionHandler("/Home/Error"); will not cause the Error page to be hit, however, the exception will get added to the database.

How can I add an entry to my database, then return the Error page?

For completeness, I'm just throwing a new exception in the Index method on the HomeController to test this, and the code in UncaughtExceptionHandler is

public class UncaughtExceptionHandler
{
    public async Task LogUnhandledException(Exception exception, string connectionString)
    {
        DbContextOptionsBuilder<DbSh> builder = new DbContextOptionsBuilder<DbSh>();

        builder.UseSqlServer(connectionString);

        DbSh dbForUnhandledError = new DbSh(builder.Options);

        string message = exception.Message;
        if (message != null && message.Length > 32) message = message.Substring(0, 32);

        Error error = new Error(exception, "Exception caught in ShWeb.Infrastructure.UncaughtExceptionHandler");

        dbForUnhandledError.Errors.Add(error);

        var result = await dbForUnhandledError.SaveChangesAsync();

        dbForUnhandledError.Dispose();
    }
}

Upvotes: 1

Views: 785

Answers (1)

MikeT
MikeT

Reputation: 2663

Ach, just needed to add context.Response.Redirect("/About/Error");

So the code is

app.UseExceptionHandler(configure =>
{
    configure.Run(async context =>
    {
        UncaughtExceptionHandler uncaughtExceptionHandler = new UncaughtExceptionHandler();

        await uncaughtExceptionHandler.LogUnhandledException(
            context.Features.Get<IExceptionHandlerFeature>().Error,
            Configuration.GetConnectionString("RemoteConnection"));

        context.Response.Redirect("/Home/Error");
    });
});

Upvotes: 1

Related Questions