Skip to content

Commit

Permalink
Fix DatabaseDeveloperPageExceptionFilter to handle wrapped DbExceptions
Browse files Browse the repository at this point in the history
Sometimes EF (or other libraries) wrap database errors. The exception filter should account for this, but was not doing. This was revealed by dotnet/efcore#25050 where we started treating more error numbers as transient and hence wrapping their exceptions.

Note that the original Diagnostics.EFCore.FunctionalTests have a test for this, but it appears that these tests were never updated when the mechanism was changed in .NET 5.
  • Loading branch information
ajcvickers authored and Pilchie committed Sep 21, 2021
1 parent 1add775 commit a50363f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ public DatabaseDeveloperPageExceptionFilter(ILogger<DatabaseDeveloperPageExcepti
/// <inheritdoc />
public async Task HandleExceptionAsync(ErrorContext errorContext, Func<ErrorContext, Task> next)
{
if (!(errorContext.Exception is DbException))
var dbException = errorContext.Exception as DbException
?? errorContext.Exception?.InnerException as DbException;

if (dbException == null)
{
await next(errorContext);
return;
Expand Down Expand Up @@ -76,7 +79,7 @@ public async Task HandleExceptionAsync(ErrorContext errorContext, Func<ErrorCont
{
var page = new DatabaseErrorPage
{
Model = new DatabaseErrorPageModel(errorContext.Exception, contextDetails, _options, errorContext.HttpContext.Request.PathBase)
Model = new DatabaseErrorPageModel(dbException, contextDetails, _options, errorContext.HttpContext.Request.PathBase)
};

await page.ExecuteAsync(errorContext.HttpContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,33 @@ await filter.HandleExceptionAsync(
Assert.True(nextFilterInvoked);
}

[Fact]
public async Task Wrapped_DbExceptions_HandlingFails_InvokesNextFilter()
{
var sink = new TestSink();
var filter = new DatabaseDeveloperPageExceptionFilter(
new TestLogger<DatabaseDeveloperPageExceptionFilter>(new TestLoggerFactory(sink, true)),
Options.Create(new DatabaseErrorPageOptions()));
var context = new DefaultHttpContext();
var exception = new InvalidOperationException("Bang!", new Mock<DbException>().Object);
var nextFilterInvoked = false;

await filter.HandleExceptionAsync(
new ErrorContext(context, exception),
context =>
{
nextFilterInvoked = true;
return Task.CompletedTask;
});

Assert.True(nextFilterInvoked);
Assert.Equal(1, sink.Writes.Count);
var message = sink.Writes.Single();
Assert.Equal(LogLevel.Error, message.LogLevel);
Assert.Contains("An exception occurred while calculating the database error page content.", message.Message);
}


[Fact]
public async Task DbExceptions_HandlingFails_InvokesNextFilter()
{
Expand Down

0 comments on commit a50363f

Please sign in to comment.