Skip to content

Commit c21e293

Browse files
author
John Luo
committed
Obsolete error page middleware
1 parent b0ed5b2 commit c21e293

File tree

13 files changed

+160
-102
lines changed

13 files changed

+160
-102
lines changed

src/Middleware/Diagnostics.EntityFrameworkCore/src/DatabaseErrorPageExtensions.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Microsoft.AspNetCore.Builder
1111
/// <summary>
1212
/// <see cref="IApplicationBuilder"/> extension methods for the <see cref="DatabaseErrorPageMiddleware"/>.
1313
/// </summary>
14+
[Obsolete("This is obsolete and will be removed in a future version. Use DatabaseExceptionHandler instead.")]
1415
public static class DatabaseErrorPageExtensions
1516
{
1617
/// <summary>
@@ -19,6 +20,7 @@ public static class DatabaseErrorPageExtensions
1920
/// </summary>
2021
/// <param name="app">The <see cref="IApplicationBuilder"/> to register the middleware with.</param>
2122
/// <returns>The same <see cref="IApplicationBuilder"/> instance so that multiple calls can be chained.</returns>
23+
[Obsolete("This is obsolete and will be removed in a future version. Use DatabaseExceptionHandler instead.")]
2224
public static IApplicationBuilder UseDatabaseErrorPage(this IApplicationBuilder app)
2325
{
2426
if (app == null)
@@ -36,6 +38,7 @@ public static IApplicationBuilder UseDatabaseErrorPage(this IApplicationBuilder
3638
/// <param name="app">The <see cref="IApplicationBuilder"/> to register the middleware with.</param>
3739
/// <param name="options">A <see cref="DatabaseErrorPageOptions"/> that specifies options for the middleware.</param>
3840
/// <returns>The same <see cref="IApplicationBuilder"/> instance so that multiple calls can be chained.</returns>
41+
[Obsolete("This is obsolete and will be removed in a future version. Use DatabaseExceptionHandler instead.")]
3942
public static IApplicationBuilder UseDatabaseErrorPage(
4043
this IApplicationBuilder app, DatabaseErrorPageOptions options)
4144
{
@@ -59,4 +62,4 @@ public static IApplicationBuilder UseDatabaseErrorPage(
5962
return app;
6063
}
6164
}
62-
}
65+
}

src/Middleware/Diagnostics.EntityFrameworkCore/src/DatabaseErrorPageMiddleware.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public void Hold(Exception exception, Type contextType)
5656
/// consumes them to detect database related exception.
5757
/// </param>
5858
/// <param name="options">The options to control what information is displayed on the error page.</param>
59+
[Obsolete("This is obsolete and will be removed in a future version. Use DatabaseExceptionHandler instead.")]
5960
public DatabaseErrorPageMiddleware(
6061
RequestDelegate next,
6162
ILoggerFactory loggerFactory,

src/Middleware/Diagnostics.EntityFrameworkCore/src/DiagnosticsEntityFrameworkCoreLoggerExtensions.cs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
@@ -14,11 +14,6 @@ internal static class DiagnosticsEntityFrameworkCoreLoggerExtensions
1414
new EventId(1, "NoContextType"),
1515
"No context type was specified. Ensure the form data from the request includes a 'context' value, specifying the context type name to apply migrations for.");
1616

17-
private static readonly Action<ILogger, string, Exception> _invalidContextType = LoggerMessage.Define<string>(
18-
LogLevel.Error,
19-
new EventId(2, "InvalidContextType"),
20-
"The context type '{ContextTypeName}' could not be loaded. Ensure this is the correct type name for the context you are trying to apply migrations for.");
21-
2217
private static readonly Action<ILogger, string, Exception> _contextNotRegistered = LoggerMessage.Define<string>(
2318
LogLevel.Error,
2419
new EventId(3, "ContextNotRegistered"),
@@ -85,11 +80,6 @@ public static void NoContextType(this ILogger logger)
8580
_noContextType(logger, null);
8681
}
8782

88-
public static void InvalidContextType(this ILogger logger, string contextTypeName)
89-
{
90-
_invalidContextType(logger, contextTypeName, null);
91-
}
92-
9383
public static void ContextNotRegistered(this ILogger logger, string contextTypeName)
9484
{
9585
_contextNotRegistered(logger, contextTypeName, null);

src/Middleware/Diagnostics.EntityFrameworkCore/src/MigrationsEndPointMiddleware.cs

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
using Microsoft.Extensions.DependencyInjection;
1212
using Microsoft.Extensions.Logging;
1313
using Microsoft.Extensions.Options;
14-
using Microsoft.Extensions.Primitives;
1514

1615
namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
1716
{
@@ -111,12 +110,7 @@ private static async Task<DbContext> GetDbContext(HttpContext context, ILogger l
111110
var form = await context.Request.ReadFormAsync();
112111
var contextTypeName = form["context"];
113112

114-
// TODO: Decouple
115-
// Look for DbContext classes registered in the service provider
116-
var registeredContexts = context.RequestServices.GetServices<DbContextOptions>()
117-
.Select(o => o.ContextType);
118-
119-
if (string.IsNullOrWhiteSpace(contextTypeName) || !registeredContexts.Any(c => string.Equals(contextTypeName, c.AssemblyQualifiedName)))
113+
if (string.IsNullOrWhiteSpace(contextTypeName))
120114
{
121115
logger.NoContextType();
122116

@@ -125,33 +119,27 @@ private static async Task<DbContext> GetDbContext(HttpContext context, ILogger l
125119
return null;
126120
}
127121

128-
var contextType = Type.GetType(contextTypeName);
122+
// TODO: Decouple
123+
// Look for DbContext classes registered in the service provider
124+
var registeredContexts = context.RequestServices.GetServices<DbContextOptions>()
125+
.Select(o => o.ContextType);
129126

130-
if (contextType == null)
127+
if (!registeredContexts.Any(c => string.Equals(contextTypeName, c.AssemblyQualifiedName)))
131128
{
132-
var message = Strings.FormatMigrationsEndPointMiddleware_InvalidContextType(contextTypeName);
129+
var message = Strings.FormatMigrationsEndPointMiddleware_ContextNotRegistered(contextTypeName);
133130

134-
logger.InvalidContextType(contextTypeName);
131+
logger.ContextNotRegistered(contextTypeName);
135132

136133
await WriteErrorToResponse(context.Response, message);
137134

138135
return null;
139136
}
140137

138+
var contextType = Type.GetType(contextTypeName);
139+
141140
// TODO: Decouple
142141
var db = (DbContext)context.RequestServices.GetService(contextType);
143142

144-
if (db == null)
145-
{
146-
var message = Strings.FormatMigrationsEndPointMiddleware_ContextNotRegistered(contextType.FullName);
147-
148-
logger.ContextNotRegistered(contextType.FullName);
149-
150-
await WriteErrorToResponse(context.Response, message);
151-
152-
return null;
153-
}
154-
155143
return db;
156144
}
157145

src/Middleware/Diagnostics.EntityFrameworkCore/src/Strings.resx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,14 +166,11 @@
166166
<value>&gt; dotnet ef database update</value>
167167
</data>
168168
<data name="MigrationsEndPointMiddleware_ContextNotRegistered" xml:space="preserve">
169-
<value>The context type '{0}' was not found in services. This usually means the context was not registered in services during startup. You probably want to call AddScoped&lt;{0}&gt;() inside the UseServices(...) call in your application startup code.</value>
169+
<value>The context type '{0}' was not found in services. This usually means either the context is invalid or it was not registered in services during startup. You probably want to call AddDBContext&lt;&gt;() inside the ConfigureServices(...) call in your application startup code.</value>
170170
</data>
171171
<data name="MigrationsEndPointMiddleware_Exception" xml:space="preserve">
172172
<value>An error occurred while applying the migrations for '{0}'. See InnerException for details.</value>
173173
</data>
174-
<data name="MigrationsEndPointMiddleware_InvalidContextType" xml:space="preserve">
175-
<value>The context type '{0}' could not be loaded. Ensure this is the correct type name for the context you are trying to apply migrations for.</value>
176-
</data>
177174
<data name="MigrationsEndPointMiddleware_NoContextType" xml:space="preserve">
178175
<value>No context type was specified. Ensure the form data from the request includes a 'context' value, specifying the context type name to apply migrations for.</value>
179176
</data>

src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/DatabaseErrorPage.Designer.cs

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/DatabaseErrorPage.cshtml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@using System
1+
@using System
22
@using System.Linq
33
@using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
44
@using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views
@@ -69,7 +69,7 @@
6969
</div>
7070
}
7171
72-
var contextWithPendingMigrations = Model.ContextDetails.Where(c => c.PendingMigrations.Any());
72+
var contextWithPendingMigrations = Model.ContextDetails.Where(c => c.PendingMigrations.Any()).Except(contextWithNoDBOrMigrations);
7373
if (contextWithPendingMigrations.Any())
7474
{
7575
<div>
@@ -135,7 +135,7 @@
135135
</div>
136136
}
137137
138-
var contextWithPendingModelChanges = Model.ContextDetails.Where(c => c.PendingModelChanges);
138+
var contextWithPendingModelChanges = Model.ContextDetails.Where(c => c.PendingModelChanges).Except(contextWithNoDBOrMigrations).Except(contextWithPendingMigrations);
139139
if (contextWithPendingModelChanges.Any())
140140
{
141141
<div>

src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/DatabaseErrorPageMiddlewareTest.cs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ public class DatabaseErrorPageMiddlewareTest
2727
[Fact]
2828
public async Task Successful_requests_pass_thru()
2929
{
30+
#pragma warning disable CS0618 // Type or member is obsolete
3031
var builder = new WebHostBuilder().Configure(app => app
3132
.UseDatabaseErrorPage()
33+
#pragma warning restore CS0618 // Type or member is obsolete
3234
.UseMiddleware<SuccessMiddleware>());
3335
var server = new TestServer(builder);
3436

@@ -53,8 +55,10 @@ public virtual async Task Invoke(HttpContext context)
5355
[Fact]
5456
public async Task Non_database_exceptions_pass_thru()
5557
{
58+
#pragma warning disable CS0618 // Type or member is obsolete
5659
var builder = new WebHostBuilder().Configure(app => app
5760
.UseDatabaseErrorPage()
61+
#pragma warning restore CS0618 // Type or member is obsolete
5862
.UseMiddleware<ExceptionMiddleware>());
5963
var server = new TestServer(builder);
6064

@@ -119,7 +123,9 @@ public async Task Error_page_displayed_no_migrations()
119123

120124
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
121125
var content = await response.Content.ReadAsStringAsync();
122-
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", typeof(BloggingContext).Name), content);
126+
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsTitle"), content);
127+
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsInfo"), content);
128+
Assert.Contains(typeof(BloggingContext).Name, content);
123129
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_AddMigrationCommandPMC").Replace(">", "&gt;"), content);
124130
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_ApplyMigrationsCommandPMC").Replace(">", "&gt;"), content);
125131
}
@@ -178,7 +184,9 @@ public async Task Error_page_displayed_pending_migrations()
178184
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
179185

180186
var content = await response.Content.ReadAsStringAsync();
181-
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingMigrationsTitle", typeof(BloggingContextWithMigrations).Name), content);
187+
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingMigrationsTitle"), content);
188+
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingMigrationsInfo"), content);
189+
Assert.Contains(typeof(BloggingContextWithMigrations).Name, content);
182190
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_ApplyMigrationsCommandPMC").Replace(">", "&gt;"), content);
183191
Assert.Contains("<li>111111111111111_MigrationOne</li>", content);
184192
Assert.Contains("<li>222222222222222_MigrationTwo</li>", content);
@@ -214,7 +222,9 @@ public async Task Error_page_displayed_pending_model_changes()
214222
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
215223

216224
var content = await response.Content.ReadAsStringAsync();
217-
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingChangesTitle", typeof(BloggingContextWithPendingModelChanges).Name), content);
225+
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingChangesTitle"), content);
226+
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingChangesInfo"), content);
227+
Assert.Contains(typeof(BloggingContextWithPendingModelChanges).Name, content);
218228
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_AddMigrationCommandCLI").Replace(">", "&gt;"), content);
219229
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_AddMigrationCommandPMC").Replace(">", "&gt;"), content);
220230
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_ApplyMigrationsCommandCLI").Replace(">", "&gt;"), content);
@@ -259,7 +269,7 @@ public async Task Error_page_then_apply_migrations()
259269
// Ensure the url we're going to test is what the page is using in it's JavaScript
260270
var javaScriptEncoder = JavaScriptEncoder.Default;
261271
Assert.Contains("req.open(\"POST\", \"" + JavaScriptEncode(expectedMigrationsEndpoint) + "\", true);", content);
262-
Assert.Contains("var formBody = \"context=" + JavaScriptEncode(UrlEncode(expectedContextType)) + "\";", content);
272+
Assert.Contains("data-assemblyname=\"" + JavaScriptEncode(expectedContextType) + "\"", content);
263273

264274
// Step Two: Request to migrations endpoint
265275
var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
@@ -305,10 +315,12 @@ public async Task Customize_migrations_end_point()
305315
var builder = new WebHostBuilder()
306316
.Configure(app =>
307317
{
318+
#pragma warning disable CS0618 // Type or member is obsolete
308319
app.UseDatabaseErrorPage(new DatabaseErrorPageOptions
309320
{
310321
MigrationsEndPointPath = new PathString(migrationsEndpoint)
311322
});
323+
#pragma warning restore CS0618 // Type or member is obsolete
312324

313325
app.UseMiddleware<PendingMigrationsMiddleware>();
314326
})
@@ -338,7 +350,9 @@ public async Task Pass_thru_when_context_not_in_services()
338350
var builder = new WebHostBuilder()
339351
.Configure(app =>
340352
{
353+
#pragma warning disable CS0618 // Type or member is obsolete
341354
app.UseDatabaseErrorPage();
355+
#pragma warning restore CS0618 // Type or member is obsolete
342356
app.UseMiddleware<ContextNotRegisteredInServicesMiddleware>();
343357
#pragma warning disable CS0618 // Type or member is obsolete
344358
app.ApplicationServices.GetService<ILoggerFactory>().AddProvider(logProvider);
@@ -436,7 +450,9 @@ public async Task Error_page_displayed_when_exception_wrapped()
436450
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
437451
var content = await response.Content.ReadAsStringAsync();
438452
Assert.Contains("I wrapped your exception", content);
439-
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", typeof(BloggingContext).Name), content);
453+
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsTitle"), content);
454+
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsInfo"), content);
455+
Assert.Contains(typeof(BloggingContext).Name, content);
440456
}
441457
}
442458

@@ -467,7 +483,9 @@ private static TestServer SetupTestServer<TContext, TMiddleware>(SqlTestStore da
467483
var builder = new WebHostBuilder()
468484
.Configure(app =>
469485
{
486+
#pragma warning disable CS0618 // Type or member is obsolete
470487
app.UseDatabaseErrorPage();
488+
#pragma warning restore CS0618 // Type or member is obsolete
471489

472490
app.UseMiddleware<TMiddleware>();
473491

src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/MigrationsEndPointMiddlewareTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ public async Task Invalid_context_type_specified()
165165
var content = await response.Content.ReadAsStringAsync();
166166

167167
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
168-
Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_InvalidContextType", typeName), content);
168+
Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_ContextNotRegistered", typeName), content);
169169
Assert.True(content.Length > 512);
170170
}
171171

@@ -186,7 +186,7 @@ public async Task Context_not_registered_in_services()
186186
var content = await response.Content.ReadAsStringAsync();
187187

188188
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
189-
Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_ContextNotRegistered", typeof(BloggingContext)), content);
189+
Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_ContextNotRegistered", typeof(BloggingContext).AssemblyQualifiedName), content);
190190
Assert.True(content.Length > 512);
191191
}
192192

0 commit comments

Comments
 (0)