React to hosting

This commit is contained in:
Hao Kung 2015-03-19 11:22:22 -07:00
parent 7a245eba5b
commit b66b2df264
5 changed files with 85 additions and 110 deletions

View File

@ -1,21 +1,19 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Diagnostics.Entity.Utilities; using Microsoft.AspNet.Diagnostics.Entity.Utilities;
using Microsoft.AspNet.Diagnostics.Entity.Views; using Microsoft.AspNet.Diagnostics.Entity.Views;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.RequestContainer;
using Microsoft.Data.Entity; using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Infrastructure; using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Internal;
using Microsoft.Data.Entity.Relational; using Microsoft.Data.Entity.Relational;
using Microsoft.Data.Entity.Relational.Migrations; using Microsoft.Data.Entity.Relational.Migrations;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Diagnostics.Entity namespace Microsoft.AspNet.Diagnostics.Entity
{ {
@ -65,37 +63,34 @@ namespace Microsoft.AspNet.Diagnostics.Entity
{ {
if (ShouldDisplayErrorPage(_loggerProvider.Logger.LastError, ex, _logger)) if (ShouldDisplayErrorPage(_loggerProvider.Logger.LastError, ex, _logger))
{ {
using (RequestServicesContainer.EnsureRequestServices(context, _serviceProvider)) var dbContextType = _loggerProvider.Logger.LastError.ContextType;
var dbContext = (DbContext)context.RequestServices.GetService(dbContextType);
if (dbContext == null)
{ {
var dbContextType = _loggerProvider.Logger.LastError.ContextType; _logger.LogError(Strings.FormatDatabaseErrorPageMiddleware_ContextNotRegistered(dbContextType.FullName));
var dbContext = (DbContext)context.RequestServices.GetService(dbContextType); }
if (dbContext == null) else
{
if (!(dbContext.Database is RelationalDatabase))
{ {
_logger.LogError(Strings.FormatDatabaseErrorPageMiddleware_ContextNotRegistered(dbContextType.FullName)); _logger.LogVerbose(Strings.DatabaseErrorPage_NotRelationalDatabase);
} }
else else
{ {
if (!(dbContext.Database is RelationalDatabase)) var databaseExists = dbContext.Database.AsRelational().Exists();
var migrator = ((IAccessor<Migrator>)dbContext.Database).Service;
var pendingMigrations = migrator.GetUnappliedMigrations().Select(m => m.Id);
var pendingModelChanges = migrator.HasPendingModelChanges();
if ((!databaseExists && pendingMigrations.Any()) || pendingMigrations.Any() || pendingModelChanges)
{ {
_logger.LogVerbose(Strings.DatabaseErrorPage_NotRelationalDatabase); var page = new DatabaseErrorPage();
} page.Model = new DatabaseErrorPageModel(dbContextType, ex, databaseExists, pendingModelChanges, pendingMigrations, _options);
else await page.ExecuteAsync(context).WithCurrentCulture();
{ return;
var databaseExists = dbContext.Database.AsRelational().Exists();
var migrator = ((IAccessor<Migrator>)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).WithCurrentCulture();
return;
}
} }
} }
} }

View File

@ -2,17 +2,14 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Diagnostics.Entity.Utilities; using Microsoft.AspNet.Diagnostics.Entity.Utilities;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.Data.Entity; using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Relational.Migrations.Infrastructure;
using Microsoft.Framework.DependencyInjection;
using System.Net;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using Microsoft.AspNet.RequestContainer;
namespace Microsoft.AspNet.Diagnostics.Entity namespace Microsoft.AspNet.Diagnostics.Entity
{ {
@ -44,29 +41,26 @@ namespace Microsoft.AspNet.Diagnostics.Entity
{ {
_logger.LogVerbose(Strings.FormatMigrationsEndPointMiddleware_RequestPathMatched(context.Request.Path)); _logger.LogVerbose(Strings.FormatMigrationsEndPointMiddleware_RequestPathMatched(context.Request.Path));
using (RequestServicesContainer.EnsureRequestServices(context, _serviceProvider)) var db = await GetDbContext(context, _logger).WithCurrentCulture();
{ if (db != null)
var db = await GetDbContext(context, _logger).WithCurrentCulture(); {
if (db != null) try
{ {
try _logger.LogVerbose(Strings.FormatMigrationsEndPointMiddleware_ApplyingMigrations(db.GetType().FullName));
{
_logger.LogVerbose(Strings.FormatMigrationsEndPointMiddleware_ApplyingMigrations(db.GetType().FullName));
db.Database.AsRelational().ApplyMigrations(); db.Database.AsRelational().ApplyMigrations();
context.Response.StatusCode = (int)HttpStatusCode.NoContent; context.Response.StatusCode = (int)HttpStatusCode.NoContent;
context.Response.Headers.Add("Pragma", new[] { "no-cache" }); context.Response.Headers.Add("Pragma", new[] { "no-cache" });
context.Response.Headers.Add("Cache-Control", new[] { "no-cache" }); context.Response.Headers.Add("Cache-Control", new[] { "no-cache" });
_logger.LogVerbose(Strings.FormatMigrationsEndPointMiddleware_Applied(db.GetType().FullName)); _logger.LogVerbose(Strings.FormatMigrationsEndPointMiddleware_Applied(db.GetType().FullName));
} }
catch (Exception ex) catch (Exception ex)
{ {
var message = Strings.FormatMigrationsEndPointMiddleware_Exception(db.GetType().FullName); var message = Strings.FormatMigrationsEndPointMiddleware_Exception(db.GetType().FullName);
_logger.LogError(message); _logger.LogError(message);
throw new InvalidOperationException(message, ex); throw new InvalidOperationException(message, ex);
}
} }
} }
} }

View File

@ -3,8 +3,9 @@
"description": "ASP.NET 5 Middleware for error handling, error pages, and diagnostics information.", "description": "ASP.NET 5 Middleware for error handling, error pages, and diagnostics information.",
"dependencies": { "dependencies": {
"Microsoft.AspNet.Diagnostics.Interfaces": "1.0.0-*", "Microsoft.AspNet.Diagnostics.Interfaces": "1.0.0-*",
"Microsoft.AspNet.RequestContainer": "1.0.0-*", "Microsoft.AspNet.Hosting": "1.0.0-*",
"Microsoft.AspNet.WebUtilities": "1.0.0-*", "Microsoft.AspNet.WebUtilities": "1.0.0-*",
"Microsoft.Framework.OptionsModel": "1.0.0-*",
"Microsoft.Framework.NotNullAttribute.Internal": { "type": "build", "version": "1.0.0-*" }, "Microsoft.Framework.NotNullAttribute.Internal": { "type": "build", "version": "1.0.0-*" },
"Microsoft.Framework.WebEncoders.Core": "1.0.0-*" "Microsoft.Framework.WebEncoders.Core": "1.0.0-*"
}, },

View File

@ -231,21 +231,20 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests
{ {
var server = TestServer.Create(app => var server = TestServer.Create(app =>
{ {
app.UseServices(services =>
{
services.AddEntityFramework().AddSqlServer();
services.AddScoped<BloggingContextWithMigrations>();
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(database.ConnectionString);
services.AddInstance<DbContextOptions>(optionsBuilder.Options);
});
var options = DatabaseErrorPageOptions.ShowAll; var options = DatabaseErrorPageOptions.ShowAll;
options.MigrationsEndPointPath = new PathString(migrationsEndpoint); options.MigrationsEndPointPath = new PathString(migrationsEndpoint);
app.UseDatabaseErrorPage(options); app.UseDatabaseErrorPage(options);
app.UseMiddleware<PendingMigrationsMiddleware>(); app.UseMiddleware<PendingMigrationsMiddleware>();
},
services =>
{
services.AddEntityFramework().AddSqlServer();
services.AddScoped<BloggingContextWithMigrations>();
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(database.ConnectionString);
services.AddInstance<DbContextOptions>(optionsBuilder.Options);
}); });
HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/"); HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
@ -266,21 +265,16 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests
var server = TestServer.Create(app => var server = TestServer.Create(app =>
{ {
app.UseServices(services =>
{
services.AddEntityFramework()
.AddSqlServer();
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(database.ConnectionString);
services.AddInstance<DbContextOptions>(optionsBuilder.Options);
});
app.UseDatabaseErrorPage(); app.UseDatabaseErrorPage();
app.UseMiddleware<ContextNotRegisteredInServicesMiddleware>(); app.UseMiddleware<ContextNotRegisteredInServicesMiddleware>();
app.ApplicationServices.GetService<ILoggerFactory>().AddProvider(logProvider); app.ApplicationServices.GetService<ILoggerFactory>().AddProvider(logProvider);
},
services =>
{
services.AddEntityFramework().AddSqlServer();
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(database.ConnectionString);
services.AddInstance<DbContextOptions>(optionsBuilder.Options);
}); });
var ex = await Assert.ThrowsAsync<SqlException>(async () => var ex = await Assert.ThrowsAsync<SqlException>(async () =>
@ -383,18 +377,6 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests
{ {
return TestServer.Create(app => return TestServer.Create(app =>
{ {
app.UseServices(services =>
{
services.AddEntityFramework()
.AddSqlServer();
services.AddScoped<TContext>();
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(database.ConnectionString);
services.AddInstance<DbContextOptions>(optionsBuilder.Options);
});
app.UseDatabaseErrorPage(); app.UseDatabaseErrorPage();
app.UseMiddleware<TMiddleware>(); app.UseMiddleware<TMiddleware>();
@ -403,6 +385,17 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests
{ {
app.ApplicationServices.GetService<ILoggerFactory>().AddProvider(logProvider); app.ApplicationServices.GetService<ILoggerFactory>().AddProvider(logProvider);
} }
},
services =>
{
services.AddEntityFramework()
.AddSqlServer();
services.AddScoped<TContext>();
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(database.ConnectionString);
services.AddInstance(optionsBuilder.Options);
}); });
} }
} }

View File

@ -17,6 +17,7 @@ using Microsoft.Data.Entity.Relational.Migrations.History;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Xunit; using Xunit;
using Microsoft.AspNet.Diagnostics.Entity.Tests.Helpers; using Microsoft.AspNet.Diagnostics.Entity.Tests.Helpers;
using Microsoft.AspNet.Hosting.Startup;
namespace Microsoft.AspNet.Diagnostics.Entity.Tests namespace Microsoft.AspNet.Diagnostics.Entity.Tests
{ {
@ -70,13 +71,6 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests
TestServer server = TestServer.Create(app => TestServer server = TestServer.Create(app =>
{ {
app.UseServices(services =>
{
services.AddEntityFramework().AddSqlServer();
services.AddScoped<BloggingContextWithMigrations>();
services.AddInstance<DbContextOptions>(optionsBuilder.Options);
});
if (useCustomPath) if (useCustomPath)
{ {
app.UseMigrationsEndPoint(new MigrationsEndPointOptions { Path = path }); app.UseMigrationsEndPoint(new MigrationsEndPointOptions { Path = path });
@ -85,6 +79,12 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests
{ {
app.UseMigrationsEndPoint(); app.UseMigrationsEndPoint();
} }
},
services =>
{
services.AddEntityFramework().AddSqlServer();
services.AddScoped<BloggingContextWithMigrations>();
services.AddInstance<DbContextOptions>(optionsBuilder.Options);
}); });
using (var db = BloggingContextWithMigrations.CreateWithoutExternalServiceProvider(optionsBuilder.Options)) using (var db = BloggingContextWithMigrations.CreateWithoutExternalServiceProvider(optionsBuilder.Options))
@ -155,14 +155,9 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests
[Fact] [Fact]
public async Task Context_not_registered_in_services() public async Task Context_not_registered_in_services()
{ {
var server = TestServer.Create(app => var server = TestServer.Create(
{ app => app.UseMigrationsEndPoint(),
app.UseServices(services => services => services.AddEntityFramework().AddSqlServer());
{
services.AddEntityFramework().AddSqlServer();
});
app.UseMigrationsEndPoint();
});
var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>> var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
{ {
@ -185,18 +180,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests
var optionsBuilder = new DbContextOptionsBuilder(); var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(database.ConnectionString); optionsBuilder.UseSqlServer(database.ConnectionString);
TestServer server = TestServer.Create(app => TestServer server = TestServer.Create(
{ app => app.UseMigrationsEndPoint(),
app.UseServices(services => services =>
{ {
services.AddEntityFramework().AddSqlServer(); services.AddEntityFramework().AddSqlServer();
services.AddScoped<BloggingContextWithSnapshotThatThrows>(); services.AddScoped<BloggingContextWithSnapshotThatThrows>();
services.AddInstance<DbContextOptions>(optionsBuilder.Options); services.AddInstance(optionsBuilder.Options);
}); });
app.UseMigrationsEndPoint();
});
var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>> var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
{ {
new KeyValuePair<string, string>("context", typeof(BloggingContextWithSnapshotThatThrows).AssemblyQualifiedName) new KeyValuePair<string, string>("context", typeof(BloggingContextWithSnapshotThatThrows).AssemblyQualifiedName)