public virtual async Task Invoke([NotNull] HttpContext context) { Check.NotNull(context, "context"); try { #if !DNXCORE50 // TODO This probably isn't the correct place for this workaround, it // needs to be called before anything is written to CallContext // http://msdn.microsoft.com/en-us/library/dn458353(v=vs.110).aspx System.Configuration.ConfigurationManager.GetSection("system.xml/xmlReader"); #endif _loggerProvider.Logger.StartLoggingForCurrentCallContext(); await _next(context); } catch (Exception ex) { try { if (ShouldDisplayErrorPage(_loggerProvider.Logger.LastError, ex, _logger)) { var dbContextType = _loggerProvider.Logger.LastError.ContextType; var dbContext = (DbContext)context.RequestServices.GetService(dbContextType); if (dbContext == null) { _logger.LogError(Strings.FormatDatabaseErrorPageMiddleware_ContextNotRegistered(dbContextType.FullName)); } else { var creator = dbContext.GetService<IDatabaseCreator>() as IRelationalDatabaseCreator; if (creator == null) { _logger.LogVerbose(Strings.DatabaseErrorPage_NotRelationalDatabase); } else { var databaseExists = creator.Exists(); var historyRepository = dbContext.GetService<IHistoryRepository>(); var migrationsAssembly = dbContext.GetService<IMigrationsAssembly>(); var modelDiffer = dbContext.GetService<IMigrationsModelDiffer>(); var appliedMigrations = historyRepository.GetAppliedMigrations(); var pendingMigrations = ( from m in migrationsAssembly.Migrations where !appliedMigrations.Any( r => string.Equals(r.MigrationId, m.Id, StringComparison.OrdinalIgnoreCase)) select m.Id) .ToList(); var pendingModelChanges = modelDiffer.HasDifferences(migrationsAssembly.ModelSnapshot?.Model, dbContext.Model); if ((!databaseExists && pendingMigrations.Any()) || pendingMigrations.Any() || pendingModelChanges) { var page = new DatabaseErrorPage(); page.Model = new DatabaseErrorPageModel(dbContextType, ex, databaseExists, pendingModelChanges, pendingMigrations, _options); await page.ExecuteAsync(context); return; } } } } } catch (Exception e) { _logger.LogError(Strings.DatabaseErrorPageMiddleware_Exception, e); } throw; } }
private static async Task<string> ExecutePage(DatabaseErrorPageOptions options, DatabaseErrorPageModel model) { var page = new DatabaseErrorPage(); var context = new Mock<HttpContext>(); var response = new Mock<HttpResponse>(); var stream = new MemoryStream(); response.Setup(r => r.Body).Returns(stream); context.Setup(c => c.Response).Returns(response.Object); page.Model = model; await page.ExecuteAsync(context.Object); var content = Encoding.ASCII.GetString(stream.ToArray()); return content; }
public virtual async Task Invoke([NotNull] HttpContext context) { Check.NotNull(context, "context"); try { #if !DNXCORE50 // TODO This probably isn't the correct place for this workaround, it // needs to be called before anything is written to CallContext // http://msdn.microsoft.com/en-us/library/dn458353(v=vs.110).aspx System.Configuration.ConfigurationManager.GetSection("system.xml/xmlReader"); #endif _loggerProvider.Logger.StartLoggingForCurrentCallContext(); await _next(context); } catch (Exception ex) { try { if (ShouldDisplayErrorPage(_loggerProvider.Logger.LastError, ex, _logger)) { var dbContextType = _loggerProvider.Logger.LastError.ContextType; var dbContext = (DbContext)context.RequestServices.GetService(dbContextType); if (dbContext == null) { _logger.LogError(Strings.FormatDatabaseErrorPageMiddleware_ContextNotRegistered(dbContextType.FullName)); } else { if (!(dbContext.Database is RelationalDatabase)) { _logger.LogVerbose(Strings.DatabaseErrorPage_NotRelationalDatabase); } else { var databaseExists = dbContext.Database.AsRelational().Exists(); var migrator = ((IAccessor<IMigrator>)dbContext.Database).Service; var pendingMigrations = migrator.GetUnappliedMigrations().Select(m => m.Id); var pendingModelChanges = migrator.HasPendingModelChanges(); if ((!databaseExists && pendingMigrations.Any()) || pendingMigrations.Any() || pendingModelChanges) { var page = new DatabaseErrorPage(); page.Model = new DatabaseErrorPageModel(dbContextType, ex, databaseExists, pendingModelChanges, pendingMigrations, _options); await page.ExecuteAsync(context); return; } } } } } catch (Exception e) { _logger.LogError(Strings.DatabaseErrorPageMiddleware_Exception, e); } throw; } }