Convert DatabaseErrorPage to exception filter (#24588)
* Convert DatabaseErrorPage middleware to exception filter
This commit is contained in:
parent
a6abd1101d
commit
cfe158cbed
|
|
@ -40,6 +40,8 @@ namespace ApiAuthSample
|
||||||
|
|
||||||
services.AddMvc()
|
services.AddMvc()
|
||||||
.AddNewtonsoftJson();
|
.AddNewtonsoftJson();
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
|
@ -48,7 +50,6 @@ namespace ApiAuthSample
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ namespace IdentitySample.DefaultUI
|
||||||
services.AddDefaultIdentity<ApplicationUser>(o => o.SignIn.RequireConfirmedAccount = true)
|
services.AddDefaultIdentity<ApplicationUser>(o => o.SignIn.RequireConfirmedAccount = true)
|
||||||
.AddRoles<IdentityRole>()
|
.AddRoles<IdentityRole>()
|
||||||
.AddEntityFrameworkStores<ApplicationDbContext>();
|
.AddEntityFrameworkStores<ApplicationDbContext>();
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -58,7 +60,6 @@ namespace IdentitySample.DefaultUI
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ namespace IdentitySample
|
||||||
// Add application services.
|
// Add application services.
|
||||||
services.AddTransient<IEmailSender, AuthMessageSender>();
|
services.AddTransient<IEmailSender, AuthMessageSender>();
|
||||||
services.AddTransient<ISmsSender, AuthMessageSender>();
|
services.AddTransient<ISmsSender, AuthMessageSender>();
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
|
@ -61,7 +63,6 @@ namespace IdentitySample
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ namespace Identity.DefaultUI.WebSite
|
||||||
options.Conventions.AuthorizePage("/Areas/Identity/Pages/Account/Logout");
|
options.Conventions.AuthorizePage("/Areas/Identity/Pages/Account/Logout");
|
||||||
})
|
})
|
||||||
.AddNewtonsoftJson();
|
.AddNewtonsoftJson();
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
|
@ -47,7 +49,6 @@ namespace Identity.DefaultUI.WebSite
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -49,9 +49,11 @@ namespace Identity.DefaultUI.WebSite
|
||||||
services.AddDefaultIdentity<TUser>()
|
services.AddDefaultIdentity<TUser>()
|
||||||
.AddRoles<IdentityRole>()
|
.AddRoles<IdentityRole>()
|
||||||
.AddEntityFrameworkStores<TContext>();
|
.AddEntityFrameworkStores<TContext>();
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
services.AddSingleton<IFileVersionProvider, FileVersionProvider>();
|
services.AddSingleton<IFileVersionProvider, FileVersionProvider>();
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
|
@ -59,11 +61,10 @@ namespace Identity.DefaultUI.WebSite
|
||||||
{
|
{
|
||||||
// This prevents running out of file watchers on some linux machines
|
// This prevents running out of file watchers on some linux machines
|
||||||
DisableFilePolling(env);
|
DisableFilePolling(env);
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ namespace Identity.DefaultUI.WebSite
|
||||||
{
|
{
|
||||||
base.ConfigureServices(services);
|
base.ConfigureServices(services);
|
||||||
services.AddMvc(options => options.EnableEndpointRouting = false);
|
services.AddMvc(options => options.EnableEndpointRouting = false);
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
|
@ -33,7 +34,6 @@ namespace Identity.DefaultUI.WebSite
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
|
{
|
||||||
|
internal class DatabaseContextDetails
|
||||||
|
{
|
||||||
|
public Type Type { get; }
|
||||||
|
public bool DatabaseExists { get; }
|
||||||
|
public bool PendingModelChanges { get; }
|
||||||
|
public IEnumerable<string> PendingMigrations { get; }
|
||||||
|
|
||||||
|
public DatabaseContextDetails(Type type, bool databaseExists, bool pendingModelChanges, IEnumerable<string> pendingMigrations)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
DatabaseExists = databaseExists;
|
||||||
|
PendingModelChanges = pendingModelChanges;
|
||||||
|
PendingMigrations = pendingMigrations;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Common;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
|
{
|
||||||
|
public sealed class DatabaseDeveloperPageExceptionFilter : IDeveloperPageExceptionFilter
|
||||||
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly DatabaseErrorPageOptions _options;
|
||||||
|
|
||||||
|
public DatabaseDeveloperPageExceptionFilter(ILogger<DatabaseDeveloperPageExceptionFilter> logger, IOptions<DatabaseErrorPageOptions> options)
|
||||||
|
{
|
||||||
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
_options = options?.Value ?? throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleExceptionAsync(ErrorContext errorContext, Func<ErrorContext, Task> next)
|
||||||
|
{
|
||||||
|
if (!(errorContext.Exception is DbException))
|
||||||
|
{
|
||||||
|
await next(errorContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Look for DbContext classes registered in the service provider
|
||||||
|
var registeredContexts = errorContext.HttpContext.RequestServices.GetServices<DbContextOptions>()
|
||||||
|
.Select(o => o.ContextType);
|
||||||
|
|
||||||
|
if (registeredContexts.Any())
|
||||||
|
{
|
||||||
|
var contextDetails = new List<DatabaseContextDetails>();
|
||||||
|
|
||||||
|
foreach (var registeredContext in registeredContexts)
|
||||||
|
{
|
||||||
|
var details = await errorContext.HttpContext.GetContextDetailsAsync(registeredContext, _logger);
|
||||||
|
|
||||||
|
if (details != null)
|
||||||
|
{
|
||||||
|
contextDetails.Add(details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contextDetails.Any(c => c.PendingModelChanges || c.PendingMigrations.Any()))
|
||||||
|
{
|
||||||
|
var page = new DatabaseErrorPage
|
||||||
|
{
|
||||||
|
Model = new DatabaseErrorPageModel(errorContext.Exception, contextDetails, _options, errorContext.HttpContext.Request.PathBase)
|
||||||
|
};
|
||||||
|
|
||||||
|
await page.ExecuteAsync(errorContext.HttpContext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.DatabaseErrorPageMiddlewareException(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
namespace Microsoft.Extensions.DependencyInjection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Service extension methods for the <see cref="DatabaseDeveloperPageExceptionFilter"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class DatabaseDeveloperPageExceptionFilterServiceExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Add response caching services.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services">The <see cref="IServiceCollection"/> for adding services.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IServiceCollection AddDatabaseDeveloperPageExceptionFilter(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
if (services == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(services));
|
||||||
|
}
|
||||||
|
|
||||||
|
services.TryAddEnumerable(new ServiceDescriptor(typeof(IDeveloperPageExceptionFilter), typeof(DatabaseDeveloperPageExceptionFilter), ServiceLifetime.Singleton));
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="IApplicationBuilder"/> extension methods for the <see cref="DatabaseErrorPageMiddleware"/>.
|
/// <see cref="IApplicationBuilder"/> extension methods for the <see cref="DatabaseErrorPageMiddleware"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("This is obsolete and will be removed in a future version. Use DatabaseDeveloperPageExceptionFilter instead, see documentation at https://aka.ms/DatabaseDeveloperPageExceptionFilter.")]
|
||||||
public static class DatabaseErrorPageExtensions
|
public static class DatabaseErrorPageExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -19,6 +20,7 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="app">The <see cref="IApplicationBuilder"/> to register the middleware with.</param>
|
/// <param name="app">The <see cref="IApplicationBuilder"/> to register the middleware with.</param>
|
||||||
/// <returns>The same <see cref="IApplicationBuilder"/> instance so that multiple calls can be chained.</returns>
|
/// <returns>The same <see cref="IApplicationBuilder"/> instance so that multiple calls can be chained.</returns>
|
||||||
|
[Obsolete("This is obsolete and will be removed in a future version. Use DatabaseDeveloperPageExceptionFilter instead, see documentation at https://aka.ms/DatabaseDeveloperPageExceptionFilter.")]
|
||||||
public static IApplicationBuilder UseDatabaseErrorPage(this IApplicationBuilder app)
|
public static IApplicationBuilder UseDatabaseErrorPage(this IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
if (app == null)
|
if (app == null)
|
||||||
|
|
@ -36,6 +38,7 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
/// <param name="app">The <see cref="IApplicationBuilder"/> to register the middleware with.</param>
|
/// <param name="app">The <see cref="IApplicationBuilder"/> to register the middleware with.</param>
|
||||||
/// <param name="options">A <see cref="DatabaseErrorPageOptions"/> that specifies options for the middleware.</param>
|
/// <param name="options">A <see cref="DatabaseErrorPageOptions"/> that specifies options for the middleware.</param>
|
||||||
/// <returns>The same <see cref="IApplicationBuilder"/> instance so that multiple calls can be chained.</returns>
|
/// <returns>The same <see cref="IApplicationBuilder"/> instance so that multiple calls can be chained.</returns>
|
||||||
|
[Obsolete("This is obsolete and will be removed in a future version. Use DatabaseDeveloperPageExceptionFilter instead, see documentation at https://aka.ms/DatabaseDeveloperPageExceptionFilter.")]
|
||||||
public static IApplicationBuilder UseDatabaseErrorPage(
|
public static IApplicationBuilder UseDatabaseErrorPage(
|
||||||
this IApplicationBuilder app, DatabaseErrorPageOptions options)
|
this IApplicationBuilder app, DatabaseErrorPageOptions options)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,6 @@ using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
|
@ -56,6 +50,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
/// consumes them to detect database related exception.
|
/// consumes them to detect database related exception.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="options">The options to control what information is displayed on the error page.</param>
|
/// <param name="options">The options to control what information is displayed on the error page.</param>
|
||||||
|
[Obsolete("This is obsolete and will be removed in a future version. Use DatabaseDeveloperPageExceptionFilter instead, see documentation at https://aka.ms/DatabaseDeveloperPageExceptionFilter.")]
|
||||||
public DatabaseErrorPageMiddleware(
|
public DatabaseErrorPageMiddleware(
|
||||||
RequestDelegate next,
|
RequestDelegate next,
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
|
|
@ -101,7 +96,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
{
|
{
|
||||||
// Because CallContext is cloned at each async operation we cannot
|
// Because CallContext is cloned at each async operation we cannot
|
||||||
// lazily create the error object when an error is encountered, otherwise
|
// lazily create the error object when an error is encountered, otherwise
|
||||||
// it will not be available to code outside of the current async context.
|
// it will not be available to code outside of the current async context.
|
||||||
// We create it ahead of time so that any cloning just clones the reference
|
// We create it ahead of time so that any cloning just clones the reference
|
||||||
// to the object that will hold any errors.
|
// to the object that will hold any errors.
|
||||||
|
|
||||||
|
|
@ -116,81 +111,18 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
if (ShouldDisplayErrorPage(exception))
|
if (ShouldDisplayErrorPage(exception))
|
||||||
{
|
{
|
||||||
var contextType = _localDiagnostic.Value.ContextType;
|
var contextType = _localDiagnostic.Value.ContextType;
|
||||||
var context = (DbContext)httpContext.RequestServices.GetService(contextType);
|
var details = await httpContext.GetContextDetailsAsync(contextType, _logger);
|
||||||
|
|
||||||
if (context == null)
|
if (details != null && (details.PendingModelChanges || details.PendingMigrations.Count() > 0))
|
||||||
{
|
{
|
||||||
_logger.ContextNotRegisteredDatabaseErrorPageMiddleware(contextType.FullName);
|
var page = new DatabaseErrorPage
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var relationalDatabaseCreator = context.GetService<IDatabaseCreator>() as IRelationalDatabaseCreator;
|
|
||||||
if (relationalDatabaseCreator == null)
|
|
||||||
{
|
{
|
||||||
_logger.NotRelationalDatabase();
|
Model = new DatabaseErrorPageModel(exception, new DatabaseContextDetails[] { details }, _options, httpContext.Request.PathBase)
|
||||||
}
|
};
|
||||||
else
|
|
||||||
{
|
|
||||||
var databaseExists = await relationalDatabaseCreator.ExistsAsync();
|
|
||||||
|
|
||||||
if (databaseExists)
|
await page.ExecuteAsync(httpContext);
|
||||||
{
|
|
||||||
databaseExists = await relationalDatabaseCreator.HasTablesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
var migrationsAssembly = context.GetService<IMigrationsAssembly>();
|
return;
|
||||||
var modelDiffer = context.GetService<IMigrationsModelDiffer>();
|
|
||||||
|
|
||||||
var snapshotModel = migrationsAssembly.ModelSnapshot?.Model;
|
|
||||||
if (snapshotModel is IConventionModel conventionModel)
|
|
||||||
{
|
|
||||||
var conventionSet = context.GetService<IConventionSetBuilder>().CreateConventionSet();
|
|
||||||
|
|
||||||
var typeMappingConvention = conventionSet.ModelFinalizingConventions.OfType<TypeMappingConvention>().FirstOrDefault();
|
|
||||||
if (typeMappingConvention != null)
|
|
||||||
{
|
|
||||||
typeMappingConvention.ProcessModelFinalizing(conventionModel.Builder, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
var relationalModelConvention = conventionSet.ModelFinalizedConventions.OfType<RelationalModelConvention>().FirstOrDefault();
|
|
||||||
if (relationalModelConvention != null)
|
|
||||||
{
|
|
||||||
snapshotModel = relationalModelConvention.ProcessModelFinalized(conventionModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snapshotModel is IMutableModel mutableModel)
|
|
||||||
{
|
|
||||||
snapshotModel = mutableModel.FinalizeModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasDifferences will return true if there is no model snapshot, but if there is an existing database
|
|
||||||
// and no model snapshot then we don't want to show the error page since they are most likely targeting
|
|
||||||
// and existing database and have just misconfigured their model
|
|
||||||
|
|
||||||
var pendingModelChanges
|
|
||||||
= (!databaseExists || migrationsAssembly.ModelSnapshot != null)
|
|
||||||
&& modelDiffer.HasDifferences(snapshotModel?.GetRelationalModel(), context.Model.GetRelationalModel());
|
|
||||||
|
|
||||||
var pendingMigrations
|
|
||||||
= (databaseExists
|
|
||||||
? await context.Database.GetPendingMigrationsAsync()
|
|
||||||
: context.Database.GetMigrations())
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
if (pendingModelChanges || pendingMigrations.Length > 0)
|
|
||||||
{
|
|
||||||
var page = new DatabaseErrorPage
|
|
||||||
{
|
|
||||||
Model = new DatabaseErrorPageModel(
|
|
||||||
contextType, exception, databaseExists, pendingModelChanges, pendingMigrations, _options)
|
|
||||||
};
|
|
||||||
|
|
||||||
await page.ExecuteAsync(httpContext);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. 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;
|
||||||
|
|
@ -14,11 +14,6 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
new EventId(1, "NoContextType"),
|
new EventId(1, "NoContextType"),
|
||||||
"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.");
|
"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.");
|
||||||
|
|
||||||
private static readonly Action<ILogger, string, Exception> _invalidContextType = LoggerMessage.Define<string>(
|
|
||||||
LogLevel.Error,
|
|
||||||
new EventId(2, "InvalidContextType"),
|
|
||||||
"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.");
|
|
||||||
|
|
||||||
private static readonly Action<ILogger, string, Exception> _contextNotRegistered = LoggerMessage.Define<string>(
|
private static readonly Action<ILogger, string, Exception> _contextNotRegistered = LoggerMessage.Define<string>(
|
||||||
LogLevel.Error,
|
LogLevel.Error,
|
||||||
new EventId(3, "ContextNotRegistered"),
|
new EventId(3, "ContextNotRegistered"),
|
||||||
|
|
@ -85,11 +80,6 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
_noContextType(logger, null);
|
_noContextType(logger, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InvalidContextType(this ILogger logger, string contextTypeName)
|
|
||||||
{
|
|
||||||
_invalidContextType(logger, contextTypeName, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ContextNotRegistered(this ILogger logger, string contextTypeName)
|
public static void ContextNotRegistered(this ILogger logger, string contextTypeName)
|
||||||
{
|
{
|
||||||
_contextNotRegistered(logger, contextTypeName, null);
|
_contextNotRegistered(logger, contextTypeName, null);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// 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 Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
|
{
|
||||||
|
internal static class HttpContextDatabaseContextDetailsExtensions
|
||||||
|
{
|
||||||
|
public static async ValueTask<DatabaseContextDetails?> GetContextDetailsAsync(this HttpContext httpContext, Type dbcontextType, ILogger logger)
|
||||||
|
{
|
||||||
|
var context = (DbContext?)httpContext.RequestServices.GetService(dbcontextType);
|
||||||
|
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
logger.ContextNotRegisteredDatabaseErrorPageMiddleware(dbcontextType.FullName);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var relationalDatabaseCreator = context.GetService<IDatabaseCreator>() as IRelationalDatabaseCreator;
|
||||||
|
if (relationalDatabaseCreator == null)
|
||||||
|
{
|
||||||
|
logger.NotRelationalDatabase();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var databaseExists = await relationalDatabaseCreator.ExistsAsync();
|
||||||
|
|
||||||
|
if (databaseExists)
|
||||||
|
{
|
||||||
|
databaseExists = await relationalDatabaseCreator.HasTablesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
var migrationsAssembly = context.GetService<IMigrationsAssembly>();
|
||||||
|
var modelDiffer = context.GetService<IMigrationsModelDiffer>();
|
||||||
|
|
||||||
|
var snapshotModel = migrationsAssembly.ModelSnapshot?.Model;
|
||||||
|
if (snapshotModel is IConventionModel conventionModel)
|
||||||
|
{
|
||||||
|
var conventionSet = context.GetService<IConventionSetBuilder>().CreateConventionSet();
|
||||||
|
|
||||||
|
var typeMappingConvention = conventionSet.ModelFinalizingConventions.OfType<TypeMappingConvention>().FirstOrDefault();
|
||||||
|
if (typeMappingConvention != null)
|
||||||
|
{
|
||||||
|
typeMappingConvention.ProcessModelFinalizing(conventionModel.Builder, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var relationalModelConvention = conventionSet.ModelFinalizedConventions.OfType<RelationalModelConvention>().FirstOrDefault();
|
||||||
|
if (relationalModelConvention != null)
|
||||||
|
{
|
||||||
|
snapshotModel = relationalModelConvention.ProcessModelFinalized(conventionModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshotModel is IMutableModel mutableModel)
|
||||||
|
{
|
||||||
|
snapshotModel = mutableModel.FinalizeModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasDifferences will return true if there is no model snapshot, but if there is an existing database
|
||||||
|
// and no model snapshot then we don't want to show the error page since they are most likely targeting
|
||||||
|
// and existing database and have just misconfigured their model
|
||||||
|
|
||||||
|
return new DatabaseContextDetails(
|
||||||
|
type: dbcontextType,
|
||||||
|
databaseExists: databaseExists,
|
||||||
|
pendingModelChanges: (!databaseExists || migrationsAssembly.ModelSnapshot != null)
|
||||||
|
&& modelDiffer.HasDifferences(snapshotModel?.GetRelationalModel(), context.Model.GetRelationalModel()),
|
||||||
|
pendingMigrations: databaseExists
|
||||||
|
? await context.Database.GetPendingMigrationsAsync()
|
||||||
|
: context.Database.GetMigrations());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Diagnostics.Abstractions" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Http.Abstractions" />
|
<Reference Include="Microsoft.AspNetCore.Http.Abstractions" />
|
||||||
<Reference Include="Microsoft.EntityFrameworkCore.Relational" />
|
<Reference Include="Microsoft.EntityFrameworkCore.Relational" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@
|
||||||
// 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.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
|
@ -72,9 +74,10 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
|
|
||||||
if (db != null)
|
if (db != null)
|
||||||
{
|
{
|
||||||
|
var dbName = db.GetType().FullName;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.ApplyingMigrations(db.GetType().FullName);
|
_logger.ApplyingMigrations(dbName);
|
||||||
|
|
||||||
await db.Database.MigrateAsync();
|
await db.Database.MigrateAsync();
|
||||||
|
|
||||||
|
|
@ -82,13 +85,13 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
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,no-store" });
|
context.Response.Headers.Add("Cache-Control", new[] { "no-cache,no-store" });
|
||||||
|
|
||||||
_logger.MigrationsApplied(db.GetType().FullName);
|
_logger.MigrationsApplied(dbName);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var message = Strings.FormatMigrationsEndPointMiddleware_Exception(db.GetType().FullName) + ex;
|
var message = Strings.FormatMigrationsEndPointMiddleware_Exception(dbName) + ex;
|
||||||
|
|
||||||
_logger.MigrationsEndPointMiddlewareException(db.GetType().FullName, ex);
|
_logger.MigrationsEndPointMiddlewareException(dbName, ex);
|
||||||
|
|
||||||
throw new InvalidOperationException(message, ex);
|
throw new InvalidOperationException(message, ex);
|
||||||
}
|
}
|
||||||
|
|
@ -114,32 +117,25 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Look for DbContext classes registered in the service provider
|
||||||
|
var registeredContexts = context.RequestServices.GetServices<DbContextOptions>()
|
||||||
|
.Select(o => o.ContextType);
|
||||||
|
|
||||||
|
if (!registeredContexts.Any(c => string.Equals(contextTypeName, c.AssemblyQualifiedName)))
|
||||||
|
{
|
||||||
|
var message = Strings.FormatMigrationsEndPointMiddleware_ContextNotRegistered(contextTypeName);
|
||||||
|
|
||||||
|
logger.ContextNotRegistered(contextTypeName);
|
||||||
|
|
||||||
|
await WriteErrorToResponse(context.Response, message);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var contextType = Type.GetType(contextTypeName);
|
var contextType = Type.GetType(contextTypeName);
|
||||||
|
|
||||||
if (contextType == null)
|
|
||||||
{
|
|
||||||
var message = Strings.FormatMigrationsEndPointMiddleware_InvalidContextType(contextTypeName);
|
|
||||||
|
|
||||||
logger.InvalidContextType(contextTypeName);
|
|
||||||
|
|
||||||
await WriteErrorToResponse(context.Response, message);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var db = (DbContext)context.RequestServices.GetService(contextType);
|
var db = (DbContext)context.RequestServices.GetService(contextType);
|
||||||
|
|
||||||
if (db == null)
|
|
||||||
{
|
|
||||||
var message = Strings.FormatMigrationsEndPointMiddleware_ContextNotRegistered(contextType.FullName);
|
|
||||||
|
|
||||||
logger.ContextNotRegistered(contextType.FullName);
|
|
||||||
|
|
||||||
await WriteErrorToResponse(context.Response, message);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
|
|
@ -148,32 +148,29 @@
|
||||||
<value>In Visual Studio, use the Package Manager Console to scaffold a new migration and apply it to the database:</value>
|
<value>In Visual Studio, use the Package Manager Console to scaffold a new migration and apply it to the database:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DatabaseErrorPage_NoDbOrMigrationsTitle" xml:space="preserve">
|
<data name="DatabaseErrorPage_NoDbOrMigrationsTitle" xml:space="preserve">
|
||||||
<value>Use migrations to create the database for {0}</value>
|
<value>Use migrations to create the database</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DatabaseErrorPage_PendingChangesInfoPMC" xml:space="preserve">
|
<data name="DatabaseErrorPage_PendingChangesInfoPMC" xml:space="preserve">
|
||||||
<value>In Visual Studio, use the Package Manager Console to scaffold a new migration for these changes and apply them to the database:</value>
|
<value>In Visual Studio, use the Package Manager Console to scaffold a new migration for these changes and apply them to the database:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DatabaseErrorPage_PendingChangesTitle" xml:space="preserve">
|
<data name="DatabaseErrorPage_PendingChangesTitle" xml:space="preserve">
|
||||||
<value>There are pending model changes for {0}</value>
|
<value>There are pending model changes</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DatabaseErrorPage_PendingMigrationsInfo" xml:space="preserve">
|
<data name="DatabaseErrorPage_PendingMigrationsInfo" xml:space="preserve">
|
||||||
<value>There are migrations for {0} that have not been applied to the database</value>
|
<value>There are migrations that have not been applied to the following database(s):</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DatabaseErrorPage_PendingMigrationsTitle" xml:space="preserve">
|
<data name="DatabaseErrorPage_PendingMigrationsTitle" xml:space="preserve">
|
||||||
<value>Applying existing migrations for {0} may resolve this issue</value>
|
<value>Applying existing migrations may resolve this issue</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DatabaseErrorPage_ApplyMigrationsCommandCLI" xml:space="preserve">
|
<data name="DatabaseErrorPage_ApplyMigrationsCommandCLI" xml:space="preserve">
|
||||||
<value>> dotnet ef database update</value>
|
<value>> dotnet ef database update</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MigrationsEndPointMiddleware_ContextNotRegistered" xml:space="preserve">
|
<data name="MigrationsEndPointMiddleware_ContextNotRegistered" xml:space="preserve">
|
||||||
<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<{0}>() inside the UseServices(...) call in your application startup code.</value>
|
<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<>() inside the ConfigureServices(...) call in your application startup code.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MigrationsEndPointMiddleware_Exception" xml:space="preserve">
|
<data name="MigrationsEndPointMiddleware_Exception" xml:space="preserve">
|
||||||
<value>An error occurred while applying the migrations for '{0}'. See InnerException for details.</value>
|
<value>An error occurred while applying the migrations for '{0}'. See InnerException for details.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MigrationsEndPointMiddleware_InvalidContextType" xml:space="preserve">
|
|
||||||
<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>
|
|
||||||
</data>
|
|
||||||
<data name="MigrationsEndPointMiddleware_NoContextType" xml:space="preserve">
|
<data name="MigrationsEndPointMiddleware_NoContextType" xml:space="preserve">
|
||||||
<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>
|
<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>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -198,4 +195,10 @@
|
||||||
<data name="DatabaseErrorPage_HowToApplyFromCLI" xml:space="preserve">
|
<data name="DatabaseErrorPage_HowToApplyFromCLI" xml:space="preserve">
|
||||||
<value>Alternatively, you can apply pending migrations from a command prompt at your project directory:</value>
|
<value>Alternatively, you can apply pending migrations from a command prompt at your project directory:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DatabaseErrorPage_NoDbOrMigrationsInfo" xml:space="preserve">
|
||||||
|
<value>A database needs to be created for the following:</value>
|
||||||
|
</data>
|
||||||
|
<data name="DatabaseErrorPage_PendingChangesInfo" xml:space="preserve">
|
||||||
|
<value>Pending model changes are detected in the following:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -4,31 +4,40 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views
|
||||||
{
|
{
|
||||||
#line hidden
|
#line hidden
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
#nullable restore
|
||||||
#line 1 "DatabaseErrorPage.cshtml"
|
#line 1 "DatabaseErrorPage.cshtml"
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
#nullable restore
|
||||||
#line 2 "DatabaseErrorPage.cshtml"
|
#line 2 "DatabaseErrorPage.cshtml"
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
#nullable restore
|
||||||
#line 3 "DatabaseErrorPage.cshtml"
|
#line 3 "DatabaseErrorPage.cshtml"
|
||||||
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore;
|
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore;
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
#nullable restore
|
||||||
#line 4 "DatabaseErrorPage.cshtml"
|
#line 4 "DatabaseErrorPage.cshtml"
|
||||||
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
|
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
internal class DatabaseErrorPage : Microsoft.Extensions.RazorViews.BaseView
|
internal class DatabaseErrorPage : Microsoft.Extensions.RazorViews.BaseView
|
||||||
{
|
{
|
||||||
#pragma warning disable 1998
|
#pragma warning disable 1998
|
||||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||||
{
|
{
|
||||||
|
#nullable restore
|
||||||
#line 5 "DatabaseErrorPage.cshtml"
|
#line 5 "DatabaseErrorPage.cshtml"
|
||||||
|
|
||||||
Response.StatusCode = 500;
|
Response.StatusCode = 500;
|
||||||
|
|
@ -37,6 +46,7 @@ using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral(@"<!DOCTYPE html>
|
WriteLiteral(@"<!DOCTYPE html>
|
||||||
|
|
||||||
<html lang=""en"" xmlns=""http://www.w3.org/1999/xhtml"">
|
<html lang=""en"" xmlns=""http://www.w3.org/1999/xhtml"">
|
||||||
|
|
@ -128,156 +138,265 @@ body .titleerror {
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>");
|
<h1>");
|
||||||
|
#nullable restore
|
||||||
#line 113 "DatabaseErrorPage.cshtml"
|
#line 113 "DatabaseErrorPage.cshtml"
|
||||||
Write(Strings.DatabaseErrorPage_Title);
|
Write(Strings.DatabaseErrorPage_Title);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral("</h1>\r\n <p>\r\n");
|
WriteLiteral("</h1>\r\n <p>\r\n");
|
||||||
|
#nullable restore
|
||||||
#line 115 "DatabaseErrorPage.cshtml"
|
#line 115 "DatabaseErrorPage.cshtml"
|
||||||
for (Exception ex = Model.Exception; ex != null; ex = ex.InnerException)
|
for (Exception ex = Model.Exception; ex != null; ex = ex.InnerException)
|
||||||
{
|
{
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral(" <span>");
|
WriteLiteral(" <span>");
|
||||||
|
#nullable restore
|
||||||
#line 117 "DatabaseErrorPage.cshtml"
|
#line 117 "DatabaseErrorPage.cshtml"
|
||||||
Write(ex.GetType().Name);
|
Write(ex.GetType().Name);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral(": ");
|
WriteLiteral(": ");
|
||||||
|
#nullable restore
|
||||||
#line 117 "DatabaseErrorPage.cshtml"
|
#line 117 "DatabaseErrorPage.cshtml"
|
||||||
Write(ex.Message);
|
Write(ex.Message);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral("</span>\r\n <br />\r\n");
|
WriteLiteral("</span>\r\n <br />\r\n");
|
||||||
|
#nullable restore
|
||||||
#line 119 "DatabaseErrorPage.cshtml"
|
#line 119 "DatabaseErrorPage.cshtml"
|
||||||
}
|
}
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral(" </p>\r\n <hr />\r\n\r\n");
|
WriteLiteral(" </p>\r\n <hr />\r\n\r\n");
|
||||||
|
#nullable restore
|
||||||
#line 123 "DatabaseErrorPage.cshtml"
|
#line 123 "DatabaseErrorPage.cshtml"
|
||||||
if (!Model.DatabaseExists && !Model.PendingMigrations.Any())
|
|
||||||
{
|
var contextWithNoDBOrMigrations = Model.ContextDetails.Where(c => !c.DatabaseExists && !c.PendingMigrations.Any());
|
||||||
|
if (contextWithNoDBOrMigrations.Any())
|
||||||
|
{
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral(" <h2>");
|
#nullable disable
|
||||||
#line 125 "DatabaseErrorPage.cshtml"
|
WriteLiteral(" <div>\r\n <h2>");
|
||||||
Write(Strings.FormatDatabaseErrorPage_NoDbOrMigrationsTitle(Model.ContextType.Name));
|
#nullable restore
|
||||||
|
#line 128 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_NoDbOrMigrationsTitle);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral("</h2>\r\n <p>");
|
#nullable disable
|
||||||
#line 126 "DatabaseErrorPage.cshtml"
|
WriteLiteral("</h2>\r\n <p>");
|
||||||
Write(Strings.DatabaseErrorPage_NoDbOrMigrationsInfoPMC);
|
#nullable restore
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</p>\r\n <code> ");
|
|
||||||
#line 127 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(Strings.DatabaseErrorPage_AddMigrationCommandPMC);
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</code>\r\n <br />\r\n <code> ");
|
|
||||||
#line 129 "DatabaseErrorPage.cshtml"
|
#line 129 "DatabaseErrorPage.cshtml"
|
||||||
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC);
|
Write(Strings.DatabaseErrorPage_NoDbOrMigrationsInfo);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral("</code>\r\n <p>");
|
#nullable disable
|
||||||
#line 130 "DatabaseErrorPage.cshtml"
|
WriteLiteral("</p>\r\n\r\n <ul>\r\n");
|
||||||
Write(Strings.DatabaseErrorPage_NoDbOrMigrationsInfoCLI);
|
#nullable restore
|
||||||
|
#line 132 "DatabaseErrorPage.cshtml"
|
||||||
|
foreach (var context in contextWithNoDBOrMigrations)
|
||||||
|
{
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral("</p>\r\n <code> ");
|
#nullable disable
|
||||||
#line 131 "DatabaseErrorPage.cshtml"
|
WriteLiteral(" <li>");
|
||||||
Write(Strings.DatabaseErrorPage_AddMigrationCommandCLI);
|
#nullable restore
|
||||||
|
#line 134 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(context.Type.Name);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral("</code>\r\n <br />\r\n <code> ");
|
#nullable disable
|
||||||
#line 133 "DatabaseErrorPage.cshtml"
|
WriteLiteral("</li>\r\n");
|
||||||
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI);
|
#nullable restore
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</code>\r\n <hr />\r\n");
|
|
||||||
#line 135 "DatabaseErrorPage.cshtml"
|
#line 135 "DatabaseErrorPage.cshtml"
|
||||||
}
|
}
|
||||||
else if (Model.PendingMigrations.Any())
|
|
||||||
{
|
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral(" <div>\r\n <h2>");
|
#nullable disable
|
||||||
|
WriteLiteral(" </ul>\r\n\r\n <p>");
|
||||||
|
#nullable restore
|
||||||
|
#line 138 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_NoDbOrMigrationsInfoPMC);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</p>\r\n <code> ");
|
||||||
|
#nullable restore
|
||||||
#line 139 "DatabaseErrorPage.cshtml"
|
#line 139 "DatabaseErrorPage.cshtml"
|
||||||
Write(Strings.FormatDatabaseErrorPage_PendingMigrationsTitle(Model.ContextType.Name));
|
Write(Strings.DatabaseErrorPage_AddMigrationCommandPMC);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral("</h2>\r\n <p>");
|
#nullable disable
|
||||||
#line 140 "DatabaseErrorPage.cshtml"
|
WriteLiteral("</code>\r\n <br />\r\n <code> ");
|
||||||
Write(Strings.FormatDatabaseErrorPage_PendingMigrationsInfo(Model.ContextType.Name));
|
#nullable restore
|
||||||
|
#line 141 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral("</p>\r\n\r\n <ul>\r\n");
|
#nullable disable
|
||||||
|
WriteLiteral("</code>\r\n <p>");
|
||||||
|
#nullable restore
|
||||||
|
#line 142 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_NoDbOrMigrationsInfoCLI);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</p>\r\n <code> ");
|
||||||
|
#nullable restore
|
||||||
#line 143 "DatabaseErrorPage.cshtml"
|
#line 143 "DatabaseErrorPage.cshtml"
|
||||||
foreach (var migration in Model.PendingMigrations)
|
Write(Strings.DatabaseErrorPage_AddMigrationCommandCLI);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</code>\r\n <br />\r\n <code> ");
|
||||||
|
#nullable restore
|
||||||
|
#line 145 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</code>\r\n <hr />\r\n </div>\r\n");
|
||||||
|
#nullable restore
|
||||||
|
#line 148 "DatabaseErrorPage.cshtml"
|
||||||
|
}
|
||||||
|
|
||||||
|
var contextWithPendingMigrations = Model.ContextDetails.Where(c => c.PendingMigrations.Any()).Except(contextWithNoDBOrMigrations);
|
||||||
|
if (contextWithPendingMigrations.Any())
|
||||||
|
{
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral(" <div>\r\n <h2>");
|
||||||
|
#nullable restore
|
||||||
|
#line 154 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_PendingMigrationsTitle);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</h2>\r\n <p>");
|
||||||
|
#nullable restore
|
||||||
|
#line 155 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_PendingMigrationsInfo);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</p>\r\n\r\n");
|
||||||
|
#nullable restore
|
||||||
|
#line 157 "DatabaseErrorPage.cshtml"
|
||||||
|
foreach (var context in contextWithPendingMigrations)
|
||||||
{
|
{
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral(" <li>");
|
#nullable disable
|
||||||
#line 145 "DatabaseErrorPage.cshtml"
|
WriteLiteral(" <h3>");
|
||||||
Write(migration);
|
#nullable restore
|
||||||
|
#line 159 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(context.Type.Name);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</h3>\r\n <ul>\r\n");
|
||||||
|
#nullable restore
|
||||||
|
#line 161 "DatabaseErrorPage.cshtml"
|
||||||
|
foreach (var migration in context.PendingMigrations)
|
||||||
|
{
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral(" <li>");
|
||||||
|
#nullable restore
|
||||||
|
#line 163 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(migration);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral("</li>\r\n");
|
WriteLiteral("</li>\r\n");
|
||||||
#line 146 "DatabaseErrorPage.cshtml"
|
#nullable restore
|
||||||
|
#line 164 "DatabaseErrorPage.cshtml"
|
||||||
|
}
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral(" </ul>\r\n");
|
||||||
|
WriteLiteral(" <p>\r\n <button id=\"applyMigrations\" onclick=\"ApplyMigrations()\" data-assemblyname=\"");
|
||||||
|
#nullable restore
|
||||||
|
#line 168 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(JavaScriptEncode(context.Type.AssemblyQualifiedName));
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("\">");
|
||||||
|
#nullable restore
|
||||||
|
#line 168 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_ApplyMigrationsButton);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</button>\r\n <span id=\"applyMigrationsError\" class=\"error\"></span>\r\n <span id=\"applyMigrationsSuccess\"></span>\r\n </p>\r\n");
|
||||||
|
#nullable restore
|
||||||
|
#line 172 "DatabaseErrorPage.cshtml"
|
||||||
}
|
}
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral(" </ul>\r\n\r\n <p>\r\n <button id=\"applyMigrations\" onclick=\"ApplyMigrations()\">");
|
#nullable disable
|
||||||
#line 150 "DatabaseErrorPage.cshtml"
|
WriteLiteral("\r\n <script>\r\n function ApplyMigrations() {\r\n applyMigrations.disabled = true;\r\n applyMigrationsError.innerHTML = \"\";\r\n applyMigrations.innerHTML = \"");
|
||||||
Write(Strings.DatabaseErrorPage_ApplyMigrationsButton);
|
#nullable restore
|
||||||
|
#line 178 "DatabaseErrorPage.cshtml"
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral(@"</button>
|
|
||||||
<span id=""applyMigrationsError"" class=""error""></span>
|
|
||||||
<span id=""applyMigrationsSuccess""></span>
|
|
||||||
</p>
|
|
||||||
<script>
|
|
||||||
function ApplyMigrations() {
|
|
||||||
applyMigrations.disabled = true;
|
|
||||||
applyMigrationsError.innerHTML = """";
|
|
||||||
applyMigrations.innerHTML = """);
|
|
||||||
#line 158 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButtonRunning));
|
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButtonRunning));
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral("\";\r\n\r\n var req = new XMLHttpRequest();\r\n\r\n req.onload = function (e) {\r\n if (req.status === 204) {\r\n applyMigrations.innerHTML = \"");
|
WriteLiteral("\";\r\n\r\n var req = new XMLHttpRequest();\r\n\r\n req.onload = function (e) {\r\n if (req.status === 204) {\r\n applyMigrations.innerHTML = \"");
|
||||||
#line 164 "DatabaseErrorPage.cshtml"
|
#nullable restore
|
||||||
|
#line 184 "DatabaseErrorPage.cshtml"
|
||||||
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButtonDone));
|
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButtonDone));
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral("\";\r\n applyMigrationsSuccess.innerHTML = \"");
|
WriteLiteral("\";\r\n applyMigrationsSuccess.innerHTML = \"");
|
||||||
#line 165 "DatabaseErrorPage.cshtml"
|
#nullable restore
|
||||||
|
#line 185 "DatabaseErrorPage.cshtml"
|
||||||
Write(JavaScriptEncode(Strings.DatabaseErrorPage_MigrationsAppliedRefresh));
|
Write(JavaScriptEncode(Strings.DatabaseErrorPage_MigrationsAppliedRefresh));
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral(@""";
|
WriteLiteral(@""";
|
||||||
} else {
|
} else {
|
||||||
ErrorApplyingMigrations();
|
ErrorApplyingMigrations();
|
||||||
|
|
@ -288,18 +407,15 @@ body .titleerror {
|
||||||
ErrorApplyingMigrations();
|
ErrorApplyingMigrations();
|
||||||
};
|
};
|
||||||
|
|
||||||
var formBody = ""context=");
|
var formBody = ""context="" + encodeURIComponent(document.getElementById('applyMigrations').getAttribute('data-assemblyname'));
|
||||||
#line 175 "DatabaseErrorPage.cshtml"
|
req.open(""POST"", """);
|
||||||
Write(JavaScriptEncode(UrlEncode(Model.ContextType.AssemblyQualifiedName)));
|
#nullable restore
|
||||||
|
#line 196 "DatabaseErrorPage.cshtml"
|
||||||
#line default
|
Write(JavaScriptEncode(Model.PathBase.Add(Model.Options.MigrationsEndPointPath).Value));
|
||||||
#line hidden
|
|
||||||
WriteLiteral("\";\r\n req.open(\"POST\", \"");
|
|
||||||
#line 176 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(JavaScriptEncode(Model.Options.MigrationsEndPointPath.Value));
|
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral(@""", true);
|
WriteLiteral(@""", true);
|
||||||
req.setRequestHeader(""Content-type"", ""application/x-www-form-urlencoded"");
|
req.setRequestHeader(""Content-type"", ""application/x-www-form-urlencoded"");
|
||||||
req.send(formBody);
|
req.send(formBody);
|
||||||
|
|
@ -307,100 +423,167 @@ body .titleerror {
|
||||||
|
|
||||||
function ErrorApplyingMigrations() {
|
function ErrorApplyingMigrations() {
|
||||||
applyMigrations.innerHTML = """);
|
applyMigrations.innerHTML = """);
|
||||||
#line 182 "DatabaseErrorPage.cshtml"
|
#nullable restore
|
||||||
|
#line 202 "DatabaseErrorPage.cshtml"
|
||||||
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButton));
|
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButton));
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
WriteLiteral("\";\r\n applyMigrationsError.innerHTML = \"");
|
WriteLiteral("\";\r\n applyMigrationsError.innerHTML = \"");
|
||||||
#line 183 "DatabaseErrorPage.cshtml"
|
#nullable restore
|
||||||
|
#line 203 "DatabaseErrorPage.cshtml"
|
||||||
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsFailed));
|
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsFailed));
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral("\";\r\n applyMigrations.disabled = false;\r\n }\r\n </script>\r\n\r\n <p>");
|
#nullable disable
|
||||||
#line 188 "DatabaseErrorPage.cshtml"
|
WriteLiteral("\";\r\n applyMigrations.disabled = false;\r\n }\r\n </script>\r\n\r\n <p>");
|
||||||
Write(Strings.DatabaseErrorPage_HowToApplyFromPMC);
|
#nullable restore
|
||||||
|
#line 208 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_HowToApplyFromPMC);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral("</p>\r\n <code>");
|
#nullable disable
|
||||||
#line 189 "DatabaseErrorPage.cshtml"
|
WriteLiteral("</p>\r\n <code>");
|
||||||
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC);
|
#nullable restore
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</code>\r\n <p>");
|
|
||||||
#line 190 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(Strings.DatabaseErrorPage_HowToApplyFromCLI);
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</p>\r\n <code>");
|
|
||||||
#line 191 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI);
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</code>\r\n <hr />\r\n </div>\r\n");
|
|
||||||
#line 194 "DatabaseErrorPage.cshtml"
|
|
||||||
}
|
|
||||||
else if (Model.PendingModelChanges)
|
|
||||||
{
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral(" <div>\r\n <h2>");
|
|
||||||
#line 198 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(Strings.FormatDatabaseErrorPage_PendingChangesTitle(Model.ContextType.Name));
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</h2>\r\n <p>");
|
|
||||||
#line 199 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(Strings.DatabaseErrorPage_PendingChangesInfoPMC);
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</p>\r\n <code>");
|
|
||||||
#line 200 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(Strings.DatabaseErrorPage_AddMigrationCommandPMC);
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</code>\r\n <br />\r\n <code>");
|
|
||||||
#line 202 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC);
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</code>\r\n <p>");
|
|
||||||
#line 203 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(Strings.DatabaseErrorPage_PendingChangesInfoCLI);
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</p>\r\n <code>");
|
|
||||||
#line 204 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(Strings.DatabaseErrorPage_AddMigrationCommandCLI);
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</code>\r\n <br />\r\n <code>");
|
|
||||||
#line 206 "DatabaseErrorPage.cshtml"
|
|
||||||
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI);
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
WriteLiteral("</code>\r\n <hr />\r\n </div>\r\n");
|
|
||||||
#line 209 "DatabaseErrorPage.cshtml"
|
#line 209 "DatabaseErrorPage.cshtml"
|
||||||
}
|
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral("</body>\r\n</html>");
|
#nullable disable
|
||||||
|
WriteLiteral("</code>\r\n <p>");
|
||||||
|
#nullable restore
|
||||||
|
#line 210 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_HowToApplyFromCLI);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</p>\r\n <code>");
|
||||||
|
#nullable restore
|
||||||
|
#line 211 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</code>\r\n <hr />\r\n </div>\r\n");
|
||||||
|
#nullable restore
|
||||||
|
#line 214 "DatabaseErrorPage.cshtml"
|
||||||
|
}
|
||||||
|
|
||||||
|
var contextWithPendingModelChanges = Model.ContextDetails.Where(c => c.PendingModelChanges).Except(contextWithNoDBOrMigrations).Except(contextWithPendingMigrations);
|
||||||
|
if (contextWithPendingModelChanges.Any())
|
||||||
|
{
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral(" <div>\r\n <h2>");
|
||||||
|
#nullable restore
|
||||||
|
#line 220 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_PendingChangesTitle);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</h2>\r\n <p>");
|
||||||
|
#nullable restore
|
||||||
|
#line 221 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_PendingChangesInfo);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</p>\r\n <ul>\r\n");
|
||||||
|
#nullable restore
|
||||||
|
#line 223 "DatabaseErrorPage.cshtml"
|
||||||
|
foreach (var context in contextWithPendingModelChanges)
|
||||||
|
{
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral(" <li>");
|
||||||
|
#nullable restore
|
||||||
|
#line 225 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(context.Type.Name);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</li>\r\n");
|
||||||
|
#nullable restore
|
||||||
|
#line 226 "DatabaseErrorPage.cshtml"
|
||||||
|
}
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral(" </ul>\r\n <p>");
|
||||||
|
#nullable restore
|
||||||
|
#line 228 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_PendingChangesInfoPMC);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</p>\r\n <code>");
|
||||||
|
#nullable restore
|
||||||
|
#line 229 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_AddMigrationCommandPMC);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</code>\r\n <br />\r\n <code>");
|
||||||
|
#nullable restore
|
||||||
|
#line 231 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</code>\r\n <p>");
|
||||||
|
#nullable restore
|
||||||
|
#line 232 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_PendingChangesInfoCLI);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</p>\r\n <code>");
|
||||||
|
#nullable restore
|
||||||
|
#line 233 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_AddMigrationCommandCLI);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</code>\r\n <br />\r\n <code>");
|
||||||
|
#nullable restore
|
||||||
|
#line 235 "DatabaseErrorPage.cshtml"
|
||||||
|
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</code>\r\n <hr />\r\n </div>\r\n");
|
||||||
|
#nullable restore
|
||||||
|
#line 238 "DatabaseErrorPage.cshtml"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
|
WriteLiteral("</body>\r\n</html>\r\n");
|
||||||
}
|
}
|
||||||
#pragma warning restore 1998
|
#pragma warning restore 1998
|
||||||
|
#nullable restore
|
||||||
#line 11 "DatabaseErrorPage.cshtml"
|
#line 11 "DatabaseErrorPage.cshtml"
|
||||||
|
|
||||||
public DatabaseErrorPageModel Model { get; set; }
|
public DatabaseErrorPageModel Model { get; set; }
|
||||||
|
|
@ -417,6 +600,7 @@ body .titleerror {
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma warning restore 1591
|
#pragma warning restore 1591
|
||||||
|
|
|
||||||
|
|
@ -35,45 +35,65 @@
|
||||||
<h1>@Strings.DatabaseErrorPage_Title</h1>
|
<h1>@Strings.DatabaseErrorPage_Title</h1>
|
||||||
<p>
|
<p>
|
||||||
@for (Exception ex = Model.Exception; ex != null; ex = ex.InnerException)
|
@for (Exception ex = Model.Exception; ex != null; ex = ex.InnerException)
|
||||||
{
|
{
|
||||||
<span>@ex.GetType().Name: @ex.Message</span>
|
<span>@ex.GetType().Name: @ex.Message</span>
|
||||||
<br />
|
<br />
|
||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
@if (!Model.DatabaseExists && !Model.PendingMigrations.Any())
|
@{
|
||||||
{
|
var contextWithNoDBOrMigrations = Model.ContextDetails.Where(c => !c.DatabaseExists && !c.PendingMigrations.Any());
|
||||||
<h2>@Strings.FormatDatabaseErrorPage_NoDbOrMigrationsTitle(Model.ContextType.Name)</h2>
|
if (contextWithNoDBOrMigrations.Any())
|
||||||
<p>@Strings.DatabaseErrorPage_NoDbOrMigrationsInfoPMC</p>
|
{
|
||||||
<code> @Strings.DatabaseErrorPage_AddMigrationCommandPMC</code>
|
<div>
|
||||||
<br />
|
<h2>@Strings.DatabaseErrorPage_NoDbOrMigrationsTitle</h2>
|
||||||
<code> @Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC</code>
|
<p>@Strings.DatabaseErrorPage_NoDbOrMigrationsInfo</p>
|
||||||
<p>@Strings.DatabaseErrorPage_NoDbOrMigrationsInfoCLI</p>
|
|
||||||
<code> @Strings.DatabaseErrorPage_AddMigrationCommandCLI</code>
|
|
||||||
<br />
|
|
||||||
<code> @Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI</code>
|
|
||||||
<hr />
|
|
||||||
}
|
|
||||||
else if (Model.PendingMigrations.Any())
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<h2>@Strings.FormatDatabaseErrorPage_PendingMigrationsTitle(Model.ContextType.Name)</h2>
|
|
||||||
<p>@Strings.FormatDatabaseErrorPage_PendingMigrationsInfo(Model.ContextType.Name)</p>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@foreach (var migration in Model.PendingMigrations)
|
@foreach (var context in contextWithNoDBOrMigrations)
|
||||||
|
{
|
||||||
|
<li>@context.Type.Name</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>@Strings.DatabaseErrorPage_NoDbOrMigrationsInfoPMC</p>
|
||||||
|
<code> @Strings.DatabaseErrorPage_AddMigrationCommandPMC</code>
|
||||||
|
<br />
|
||||||
|
<code> @Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC</code>
|
||||||
|
<p>@Strings.DatabaseErrorPage_NoDbOrMigrationsInfoCLI</p>
|
||||||
|
<code> @Strings.DatabaseErrorPage_AddMigrationCommandCLI</code>
|
||||||
|
<br />
|
||||||
|
<code> @Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI</code>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
var contextWithPendingMigrations = Model.ContextDetails.Where(c => c.PendingMigrations.Any()).Except(contextWithNoDBOrMigrations);
|
||||||
|
if (contextWithPendingMigrations.Any())
|
||||||
|
{
|
||||||
|
<div>
|
||||||
|
<h2>@Strings.DatabaseErrorPage_PendingMigrationsTitle</h2>
|
||||||
|
<p>@Strings.DatabaseErrorPage_PendingMigrationsInfo</p>
|
||||||
|
|
||||||
|
@foreach (var context in contextWithPendingMigrations)
|
||||||
{
|
{
|
||||||
<li>@migration</li>
|
<h3>@context.Type.Name</h3>
|
||||||
}
|
<ul>
|
||||||
</ul>
|
@foreach (var migration in context.PendingMigrations)
|
||||||
|
{
|
||||||
|
<li>@migration</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<button id="applyMigrations" onclick="ApplyMigrations()">@Strings.DatabaseErrorPage_ApplyMigrationsButton</button>
|
<button id="applyMigrations" onclick="ApplyMigrations()" data-assemblyname="@JavaScriptEncode(context.Type.AssemblyQualifiedName)">@Strings.DatabaseErrorPage_ApplyMigrationsButton</button>
|
||||||
<span id="applyMigrationsError" class="error"></span>
|
<span id="applyMigrationsError" class="error"></span>
|
||||||
<span id="applyMigrationsSuccess"></span>
|
<span id="applyMigrationsSuccess"></span>
|
||||||
</p>
|
</p>
|
||||||
<script>
|
}
|
||||||
|
|
||||||
|
<script>
|
||||||
function ApplyMigrations() {
|
function ApplyMigrations() {
|
||||||
applyMigrations.disabled = true;
|
applyMigrations.disabled = true;
|
||||||
applyMigrationsError.innerHTML = "";
|
applyMigrationsError.innerHTML = "";
|
||||||
|
|
@ -94,8 +114,8 @@
|
||||||
ErrorApplyingMigrations();
|
ErrorApplyingMigrations();
|
||||||
};
|
};
|
||||||
|
|
||||||
var formBody = "context=@JavaScriptEncode(UrlEncode(Model.ContextType.AssemblyQualifiedName))";
|
var formBody = "context=" + encodeURIComponent(document.getElementById('applyMigrations').getAttribute('data-assemblyname'));
|
||||||
req.open("POST", "@JavaScriptEncode(Model.Options.MigrationsEndPointPath.Value)", true);
|
req.open("POST", "@JavaScriptEncode(Model.PathBase.Add(Model.Options.MigrationsEndPointPath).Value)", true);
|
||||||
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||||
req.send(formBody);
|
req.send(formBody);
|
||||||
}
|
}
|
||||||
|
|
@ -105,29 +125,39 @@
|
||||||
applyMigrationsError.innerHTML = "@JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsFailed)";
|
applyMigrationsError.innerHTML = "@JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsFailed)";
|
||||||
applyMigrations.disabled = false;
|
applyMigrations.disabled = false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<p>@Strings.DatabaseErrorPage_HowToApplyFromPMC</p>
|
<p>@Strings.DatabaseErrorPage_HowToApplyFromPMC</p>
|
||||||
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC</code>
|
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC</code>
|
||||||
<p>@Strings.DatabaseErrorPage_HowToApplyFromCLI</p>
|
<p>@Strings.DatabaseErrorPage_HowToApplyFromCLI</p>
|
||||||
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI</code>
|
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI</code>
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
else if (Model.PendingModelChanges)
|
|
||||||
{
|
var contextWithPendingModelChanges = Model.ContextDetails.Where(c => c.PendingModelChanges).Except(contextWithNoDBOrMigrations).Except(contextWithPendingMigrations);
|
||||||
<div>
|
if (contextWithPendingModelChanges.Any())
|
||||||
<h2>@Strings.FormatDatabaseErrorPage_PendingChangesTitle(Model.ContextType.Name)</h2>
|
{
|
||||||
<p>@Strings.DatabaseErrorPage_PendingChangesInfoPMC</p>
|
<div>
|
||||||
<code>@Strings.DatabaseErrorPage_AddMigrationCommandPMC</code>
|
<h2>@Strings.DatabaseErrorPage_PendingChangesTitle</h2>
|
||||||
<br />
|
<p>@Strings.DatabaseErrorPage_PendingChangesInfo</p>
|
||||||
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC</code>
|
<ul>
|
||||||
<p>@Strings.DatabaseErrorPage_PendingChangesInfoCLI</p>
|
@foreach (var context in contextWithPendingModelChanges)
|
||||||
<code>@Strings.DatabaseErrorPage_AddMigrationCommandCLI</code>
|
{
|
||||||
<br />
|
<li>@context.Type.Name</li>
|
||||||
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI</code>
|
}
|
||||||
<hr />
|
</ul>
|
||||||
</div>
|
<p>@Strings.DatabaseErrorPage_PendingChangesInfoPMC</p>
|
||||||
|
<code>@Strings.DatabaseErrorPage_AddMigrationCommandPMC</code>
|
||||||
|
<br />
|
||||||
|
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC</code>
|
||||||
|
<p>@Strings.DatabaseErrorPage_PendingChangesInfoCLI</p>
|
||||||
|
<code>@Strings.DatabaseErrorPage_AddMigrationCommandCLI</code>
|
||||||
|
<br />
|
||||||
|
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI</code>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -4,32 +4,27 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views
|
namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views
|
||||||
{
|
{
|
||||||
internal class DatabaseErrorPageModel
|
internal class DatabaseErrorPageModel
|
||||||
{
|
{
|
||||||
public DatabaseErrorPageModel(
|
public DatabaseErrorPageModel(
|
||||||
Type contextType,
|
|
||||||
Exception exception,
|
Exception exception,
|
||||||
bool databaseExists,
|
IEnumerable<DatabaseContextDetails> contextDetails,
|
||||||
bool pendingModelChanges,
|
DatabaseErrorPageOptions options,
|
||||||
IEnumerable<string> pendingMigrations,
|
PathString pathBase)
|
||||||
DatabaseErrorPageOptions options)
|
|
||||||
{
|
{
|
||||||
ContextType = contextType;
|
|
||||||
Exception = exception;
|
Exception = exception;
|
||||||
DatabaseExists = databaseExists;
|
ContextDetails = contextDetails;
|
||||||
PendingModelChanges = pendingModelChanges;
|
|
||||||
PendingMigrations = pendingMigrations;
|
|
||||||
Options = options;
|
Options = options;
|
||||||
|
PathBase = pathBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Type ContextType { get; }
|
|
||||||
public virtual Exception Exception { get; }
|
public virtual Exception Exception { get; }
|
||||||
public virtual bool DatabaseExists { get; }
|
public virtual IEnumerable<DatabaseContextDetails> ContextDetails { get; }
|
||||||
public virtual bool PendingModelChanges { get; }
|
|
||||||
public virtual IEnumerable<string> PendingMigrations { get; }
|
|
||||||
public virtual DatabaseErrorPageOptions Options { get; }
|
public virtual DatabaseErrorPageOptions Options { get; }
|
||||||
|
public virtual PathString PathBase { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,10 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
{
|
{
|
||||||
webHostBuilder
|
webHostBuilder
|
||||||
.UseTestServer()
|
.UseTestServer()
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
.Configure(app => app
|
.Configure(app => app
|
||||||
.UseDatabaseErrorPage()
|
.UseDatabaseErrorPage()
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
.UseMiddleware<SuccessMiddleware>());
|
.UseMiddleware<SuccessMiddleware>());
|
||||||
}).Build();
|
}).Build();
|
||||||
|
|
||||||
|
|
@ -68,8 +70,10 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
{
|
{
|
||||||
webHostBuilder
|
webHostBuilder
|
||||||
.UseTestServer()
|
.UseTestServer()
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
.Configure(app => app
|
.Configure(app => app
|
||||||
.UseDatabaseErrorPage()
|
.UseDatabaseErrorPage()
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
.UseMiddleware<ExceptionMiddleware>());
|
.UseMiddleware<ExceptionMiddleware>());
|
||||||
}).Build();
|
}).Build();
|
||||||
|
|
||||||
|
|
@ -140,7 +144,9 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
|
|
||||||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", typeof(BloggingContext).Name), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsTitle"), content);
|
||||||
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsInfo"), content);
|
||||||
|
Assert.Contains(typeof(BloggingContext).Name, content);
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_AddMigrationCommandPMC").Replace(">", ">"), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_AddMigrationCommandPMC").Replace(">", ">"), content);
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_ApplyMigrationsCommandPMC").Replace(">", ">"), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_ApplyMigrationsCommandPMC").Replace(">", ">"), content);
|
||||||
}
|
}
|
||||||
|
|
@ -200,7 +206,9 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||||
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingMigrationsTitle", typeof(BloggingContextWithMigrations).Name), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingMigrationsTitle"), content);
|
||||||
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingMigrationsInfo"), content);
|
||||||
|
Assert.Contains(typeof(BloggingContextWithMigrations).Name, content);
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_ApplyMigrationsCommandPMC").Replace(">", ">"), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_ApplyMigrationsCommandPMC").Replace(">", ">"), content);
|
||||||
Assert.Contains("<li>111111111111111_MigrationOne</li>", content);
|
Assert.Contains("<li>111111111111111_MigrationOne</li>", content);
|
||||||
Assert.Contains("<li>222222222222222_MigrationTwo</li>", content);
|
Assert.Contains("<li>222222222222222_MigrationTwo</li>", content);
|
||||||
|
|
@ -237,7 +245,9 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||||
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingChangesTitle", typeof(BloggingContextWithPendingModelChanges).Name), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingChangesTitle"), content);
|
||||||
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingChangesInfo"), content);
|
||||||
|
Assert.Contains(typeof(BloggingContextWithPendingModelChanges).Name, content);
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_AddMigrationCommandCLI").Replace(">", ">"), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_AddMigrationCommandCLI").Replace(">", ">"), content);
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_AddMigrationCommandPMC").Replace(">", ">"), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_AddMigrationCommandPMC").Replace(">", ">"), content);
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_ApplyMigrationsCommandCLI").Replace(">", ">"), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_ApplyMigrationsCommandCLI").Replace(">", ">"), content);
|
||||||
|
|
@ -283,7 +293,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
// Ensure the url we're going to test is what the page is using in it's JavaScript
|
// Ensure the url we're going to test is what the page is using in it's JavaScript
|
||||||
var javaScriptEncoder = JavaScriptEncoder.Default;
|
var javaScriptEncoder = JavaScriptEncoder.Default;
|
||||||
Assert.Contains("req.open(\"POST\", \"" + JavaScriptEncode(expectedMigrationsEndpoint) + "\", true);", content);
|
Assert.Contains("req.open(\"POST\", \"" + JavaScriptEncode(expectedMigrationsEndpoint) + "\", true);", content);
|
||||||
Assert.Contains("var formBody = \"context=" + JavaScriptEncode(UrlEncode(expectedContextType)) + "\";", content);
|
Assert.Contains("data-assemblyname=\"" + JavaScriptEncode(expectedContextType) + "\"", content);
|
||||||
|
|
||||||
// Step Two: Request to migrations endpoint
|
// Step Two: Request to migrations endpoint
|
||||||
var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
|
var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -333,10 +343,12 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
.UseTestServer()
|
.UseTestServer()
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
app.UseDatabaseErrorPage(new DatabaseErrorPageOptions
|
app.UseDatabaseErrorPage(new DatabaseErrorPageOptions
|
||||||
{
|
{
|
||||||
MigrationsEndPointPath = new PathString(migrationsEndpoint)
|
MigrationsEndPointPath = new PathString(migrationsEndpoint)
|
||||||
});
|
});
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
|
|
||||||
app.UseMiddleware<PendingMigrationsMiddleware>();
|
app.UseMiddleware<PendingMigrationsMiddleware>();
|
||||||
})
|
})
|
||||||
|
|
@ -374,7 +386,9 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
.UseTestServer()
|
.UseTestServer()
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
app.UseDatabaseErrorPage();
|
app.UseDatabaseErrorPage();
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
app.UseMiddleware<ContextNotRegisteredInServicesMiddleware>();
|
app.UseMiddleware<ContextNotRegisteredInServicesMiddleware>();
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
app.ApplicationServices.GetService<ILoggerFactory>().AddProvider(logProvider);
|
app.ApplicationServices.GetService<ILoggerFactory>().AddProvider(logProvider);
|
||||||
|
|
@ -478,7 +492,9 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
Assert.Contains("I wrapped your exception", content);
|
Assert.Contains("I wrapped your exception", content);
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", typeof(BloggingContext).Name), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsTitle"), content);
|
||||||
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsInfo"), content);
|
||||||
|
Assert.Contains(typeof(BloggingContext).Name, content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -513,7 +529,9 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
.UseTestServer()
|
.UseTestServer()
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
app.UseDatabaseErrorPage();
|
app.UseDatabaseErrorPage();
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
|
|
||||||
app.UseMiddleware<TMiddleware>();
|
app.UseMiddleware<TMiddleware>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||||
Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_InvalidContextType", typeName), content);
|
Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_ContextNotRegistered", typeName), content);
|
||||||
Assert.True(content.Length > 512);
|
Assert.True(content.Length > 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -228,7 +228,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||||
Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_ContextNotRegistered", typeof(BloggingContext)), content);
|
Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_ContextNotRegistered", typeof(BloggingContext).AssemblyQualifiedName), content);
|
||||||
Assert.True(content.Length > 512);
|
Assert.True(content.Length > 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. 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.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.Helpers;
|
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.Helpers;
|
||||||
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
|
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Moq;
|
using Moq;
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
{
|
{
|
||||||
public class DatabaseErrorPageTest
|
public class DatabaseErrorPageTest
|
||||||
|
|
@ -23,12 +24,17 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
var options = new DatabaseErrorPageOptions();
|
var options = new DatabaseErrorPageOptions();
|
||||||
|
|
||||||
var model = new DatabaseErrorPageModel(
|
var model = new DatabaseErrorPageModel(
|
||||||
contextType: typeof(BloggingContext),
|
new Exception(),
|
||||||
exception: new Exception(),
|
new DatabaseContextDetails[]
|
||||||
databaseExists: false,
|
{
|
||||||
pendingModelChanges: false,
|
new DatabaseContextDetails(
|
||||||
pendingMigrations: new string[] { },
|
type: typeof(BloggingContext),
|
||||||
options: options);
|
databaseExists: false,
|
||||||
|
pendingModelChanges: false,
|
||||||
|
pendingMigrations: new string[] { })
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
pathBase: PathString.Empty);
|
||||||
|
|
||||||
var content = await ExecutePage(options, model);
|
var content = await ExecutePage(options, model);
|
||||||
|
|
||||||
|
|
@ -43,12 +49,17 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
var options = new DatabaseErrorPageOptions();
|
var options = new DatabaseErrorPageOptions();
|
||||||
|
|
||||||
var model = new DatabaseErrorPageModel(
|
var model = new DatabaseErrorPageModel(
|
||||||
contextType: typeof(BloggingContext),
|
new Exception(),
|
||||||
exception: new Exception(),
|
new DatabaseContextDetails[]
|
||||||
databaseExists: false,
|
{
|
||||||
pendingModelChanges: false,
|
new DatabaseContextDetails(
|
||||||
pendingMigrations: new[] { "111_MigrationOne" },
|
type: typeof(BloggingContext),
|
||||||
options: options);
|
databaseExists: false,
|
||||||
|
pendingModelChanges: false,
|
||||||
|
pendingMigrations: new string[] { "111_MigrationOne" })
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
pathBase: PathString.Empty);
|
||||||
|
|
||||||
var content = await ExecutePage(options, model);
|
var content = await ExecutePage(options, model);
|
||||||
|
|
||||||
|
|
@ -63,12 +74,17 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
var options = new DatabaseErrorPageOptions();
|
var options = new DatabaseErrorPageOptions();
|
||||||
|
|
||||||
var model = new DatabaseErrorPageModel(
|
var model = new DatabaseErrorPageModel(
|
||||||
contextType: typeof(BloggingContext),
|
new Exception(),
|
||||||
exception: new Exception(),
|
new DatabaseContextDetails[]
|
||||||
databaseExists: true,
|
{
|
||||||
pendingModelChanges: false,
|
new DatabaseContextDetails(
|
||||||
pendingMigrations: new[] { "111_MigrationOne" },
|
type: typeof(BloggingContext),
|
||||||
options: options);
|
databaseExists: true,
|
||||||
|
pendingModelChanges: false,
|
||||||
|
pendingMigrations: new string[] { "111_MigrationOne" })
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
pathBase: PathString.Empty);
|
||||||
|
|
||||||
var content = await ExecutePage(options, model);
|
var content = await ExecutePage(options, model);
|
||||||
|
|
||||||
|
|
@ -83,12 +99,17 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
var options = new DatabaseErrorPageOptions();
|
var options = new DatabaseErrorPageOptions();
|
||||||
|
|
||||||
var model = new DatabaseErrorPageModel(
|
var model = new DatabaseErrorPageModel(
|
||||||
contextType: typeof(BloggingContext),
|
new Exception(),
|
||||||
exception: new Exception(),
|
new DatabaseContextDetails[]
|
||||||
databaseExists: true,
|
{
|
||||||
pendingModelChanges: true,
|
new DatabaseContextDetails(
|
||||||
pendingMigrations: new[] { "111_MigrationOne" },
|
type: typeof(BloggingContext),
|
||||||
options: options);
|
databaseExists: true,
|
||||||
|
pendingModelChanges: true,
|
||||||
|
pendingMigrations: new string[] { "111_MigrationOne" })
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
pathBase: PathString.Empty);
|
||||||
|
|
||||||
var content = await ExecutePage(options, model);
|
var content = await ExecutePage(options, model);
|
||||||
|
|
||||||
|
|
@ -103,12 +124,17 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
var options = new DatabaseErrorPageOptions();
|
var options = new DatabaseErrorPageOptions();
|
||||||
|
|
||||||
var model = new DatabaseErrorPageModel(
|
var model = new DatabaseErrorPageModel(
|
||||||
contextType: typeof(BloggingContext),
|
new Exception(),
|
||||||
exception: new Exception(),
|
new DatabaseContextDetails[]
|
||||||
databaseExists: true,
|
{
|
||||||
pendingModelChanges: true,
|
new DatabaseContextDetails(
|
||||||
pendingMigrations: new string[] { },
|
type: typeof(BloggingContext),
|
||||||
options: options);
|
databaseExists: true,
|
||||||
|
pendingModelChanges: true,
|
||||||
|
pendingMigrations: new string[] { })
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
pathBase: PathString.Empty);
|
||||||
|
|
||||||
var content = await ExecutePage(options, model);
|
var content = await ExecutePage(options, model);
|
||||||
|
|
||||||
|
|
@ -123,12 +149,17 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
var options = new DatabaseErrorPageOptions();
|
var options = new DatabaseErrorPageOptions();
|
||||||
|
|
||||||
var model = new DatabaseErrorPageModel(
|
var model = new DatabaseErrorPageModel(
|
||||||
contextType: typeof(BloggingContext),
|
new Exception("Something bad happened"),
|
||||||
exception: new Exception("Something bad happened"),
|
new DatabaseContextDetails[]
|
||||||
databaseExists: false,
|
{
|
||||||
pendingModelChanges: false,
|
new DatabaseContextDetails(
|
||||||
pendingMigrations: new string[] { },
|
type: typeof(BloggingContext),
|
||||||
options: options);
|
databaseExists: false,
|
||||||
|
pendingModelChanges: false,
|
||||||
|
pendingMigrations: new string[] { })
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
pathBase: PathString.Empty);
|
||||||
|
|
||||||
var content = await ExecutePage(options, model);
|
var content = await ExecutePage(options, model);
|
||||||
|
|
||||||
|
|
@ -141,12 +172,17 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
var options = new DatabaseErrorPageOptions();
|
var options = new DatabaseErrorPageOptions();
|
||||||
|
|
||||||
var model = new DatabaseErrorPageModel(
|
var model = new DatabaseErrorPageModel(
|
||||||
contextType: typeof(BloggingContext),
|
new Exception("Something bad happened", new Exception("Because something more badder happened")),
|
||||||
exception: new Exception("Something bad happened", new Exception("Because something more badder happened")),
|
new DatabaseContextDetails[]
|
||||||
databaseExists: false,
|
{
|
||||||
pendingModelChanges: false,
|
new DatabaseContextDetails(
|
||||||
pendingMigrations: new string[] { },
|
type: typeof(BloggingContext),
|
||||||
options: options);
|
databaseExists: false,
|
||||||
|
pendingModelChanges: false,
|
||||||
|
pendingMigrations: new string[] { })
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
pathBase: PathString.Empty);
|
||||||
|
|
||||||
var content = await ExecutePage(options, model);
|
var content = await ExecutePage(options, model);
|
||||||
|
|
||||||
|
|
@ -161,18 +197,46 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
options.MigrationsEndPointPath = "/HitThisEndPoint";
|
options.MigrationsEndPointPath = "/HitThisEndPoint";
|
||||||
|
|
||||||
var model = new DatabaseErrorPageModel(
|
var model = new DatabaseErrorPageModel(
|
||||||
contextType: typeof(BloggingContext),
|
new Exception(),
|
||||||
exception: new Exception(),
|
new DatabaseContextDetails[]
|
||||||
databaseExists: true,
|
{
|
||||||
pendingModelChanges: false,
|
new DatabaseContextDetails(
|
||||||
pendingMigrations: new[] { "111_MigrationOne" },
|
type: typeof(BloggingContext),
|
||||||
options: options);
|
databaseExists: true,
|
||||||
|
pendingModelChanges: false,
|
||||||
|
pendingMigrations: new string[] { "111_MigrationOne" })
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
pathBase: PathString.Empty);
|
||||||
|
|
||||||
var content = await ExecutePage(options, model);
|
var content = await ExecutePage(options, model);
|
||||||
|
|
||||||
Assert.Contains(options.MigrationsEndPointPath.Value, content);
|
Assert.Contains(options.MigrationsEndPointPath.Value, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PathBase_is_respected()
|
||||||
|
{
|
||||||
|
var options = new DatabaseErrorPageOptions();
|
||||||
|
options.MigrationsEndPointPath = "/HitThisEndPoint";
|
||||||
|
|
||||||
|
var model = new DatabaseErrorPageModel(
|
||||||
|
new Exception(),
|
||||||
|
new DatabaseContextDetails[]
|
||||||
|
{
|
||||||
|
new DatabaseContextDetails(
|
||||||
|
type: typeof(BloggingContext),
|
||||||
|
databaseExists: true,
|
||||||
|
pendingModelChanges: false,
|
||||||
|
pendingMigrations: new string[] { "111_MigrationOne" })
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
pathBase: "/PathBase");
|
||||||
|
|
||||||
|
var content = await ExecutePage(options, model);
|
||||||
|
|
||||||
|
Assert.Contains("/PathBase/HitThisEndPoint", content);
|
||||||
|
}
|
||||||
|
|
||||||
private static async Task<string> ExecutePage(DatabaseErrorPageOptions options, DatabaseErrorPageModel model)
|
private static async Task<string> ExecutePage(DatabaseErrorPageOptions options, DatabaseErrorPageModel model)
|
||||||
{
|
{
|
||||||
|
|
@ -196,4 +260,4 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,32 +10,38 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.Helpers
|
||||||
{
|
{
|
||||||
public static void DisplaysScaffoldFirstMigration(Type contextType, string content)
|
public static void DisplaysScaffoldFirstMigration(Type contextType, string content)
|
||||||
{
|
{
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", contextType.Name), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsTitle"), content);
|
||||||
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsInfo"), content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void NotDisplaysScaffoldFirstMigration(Type contextType, string content)
|
public static void NotDisplaysScaffoldFirstMigration(Type contextType, string content)
|
||||||
{
|
{
|
||||||
Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", contextType.Name), content);
|
Assert.DoesNotContain(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsTitle"), content);
|
||||||
|
Assert.DoesNotContain(StringsHelpers.GetResourceString("DatabaseErrorPage_NoDbOrMigrationsInfo"), content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DisplaysApplyMigrations(Type contextType, string content)
|
public static void DisplaysApplyMigrations(Type contextType, string content)
|
||||||
{
|
{
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingMigrationsTitle", contextType.Name), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingMigrationsTitle"), content);
|
||||||
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingMigrationsInfo"), content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void NotDisplaysApplyMigrations(Type contextType, string content)
|
public static void NotDisplaysApplyMigrations(Type contextType, string content)
|
||||||
{
|
{
|
||||||
Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingMigrationsTitle", contextType.Name), content);
|
Assert.DoesNotContain(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingMigrationsTitle"), content);
|
||||||
|
Assert.DoesNotContain(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingMigrationsInfo"), content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DisplaysScaffoldNextMigraion(Type contextType, string content)
|
public static void DisplaysScaffoldNextMigraion(Type contextType, string content)
|
||||||
{
|
{
|
||||||
Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingChangesTitle", contextType.Name), content);
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingChangesTitle"), content);
|
||||||
|
Assert.Contains(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingChangesInfo"), content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void NotDisplaysScaffoldNextMigraion(Type contextType, string content)
|
public static void NotDisplaysScaffoldNextMigraion(Type contextType, string content)
|
||||||
{
|
{
|
||||||
Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingChangesTitle", contextType.Name), content);
|
Assert.DoesNotContain(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingChangesTitle"), content);
|
||||||
|
Assert.DoesNotContain(StringsHelpers.GetResourceString("DatabaseErrorPage_PendingChangesInfo"), content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,13 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.Helpers
|
||||||
public static string GetResourceString(string stringName, params object[] parameters)
|
public static string GetResourceString(string stringName, params object[] parameters)
|
||||||
{
|
{
|
||||||
var strings = typeof(DatabaseErrorPageMiddleware).GetTypeInfo().Assembly.GetType("Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Strings").GetTypeInfo();
|
var strings = typeof(DatabaseErrorPageMiddleware).GetTypeInfo().Assembly.GetType("Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Strings").GetTypeInfo();
|
||||||
var method = strings.GetDeclaredMethods(stringName).Single();
|
var method = strings.GetDeclaredMethods(stringName).SingleOrDefault();
|
||||||
return (string)method.Invoke(null, parameters);
|
if (method != null)
|
||||||
|
{
|
||||||
|
return (string)method.Invoke(null, parameters);
|
||||||
|
}
|
||||||
|
var property = strings.GetDeclaredProperty(stringName);
|
||||||
|
return (string)property.GetValue(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@ namespace DatabaseErrorPageSample
|
||||||
public void Configure(IApplicationBuilder app)
|
public void Configure(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
app.UseDatabaseErrorPage();
|
app.UseDatabaseErrorPage();
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
app.Run(context =>
|
app.Run(context =>
|
||||||
{
|
{
|
||||||
context.RequestServices.GetService<MyContext>().Blog.FirstOrDefault();
|
context.RequestServices.GetService<MyContext>().Blog.FirstOrDefault();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
||||||
|
|
||||||
|
namespace RazorPageGenerator
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
if (args == null || args.Length < 1)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Invalid argument(s).");
|
||||||
|
Console.WriteLine(@"Usage:
|
||||||
|
dotnet razorpagegenerator <root-namespace-of-views> [path]
|
||||||
|
Examples:
|
||||||
|
dotnet razorpagegenerator Microsoft.AspNetCore.Diagnostics.RazorViews
|
||||||
|
- processes all views in ""Views"" subfolders of the current directory
|
||||||
|
dotnet razorpagegenerator Microsoft.AspNetCore.Diagnostics.RazorViews c:\project
|
||||||
|
- processes all views in ""Views"" subfolders of c:\project directory
|
||||||
|
");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rootNamespace = args[0];
|
||||||
|
var targetProjectDirectory = args.Length > 1 ? args[1] : Directory.GetCurrentDirectory();
|
||||||
|
var projectEngine = CreateProjectEngine(rootNamespace, targetProjectDirectory);
|
||||||
|
var results = MainCore(projectEngine, targetProjectDirectory);
|
||||||
|
|
||||||
|
foreach (var result in results)
|
||||||
|
{
|
||||||
|
File.WriteAllText(result.FilePath, result.GeneratedCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine($"{results.Count} files successfully generated.");
|
||||||
|
Console.WriteLine();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RazorProjectEngine CreateProjectEngine(string rootNamespace, string targetProjectDirectory, Action<RazorProjectEngineBuilder> configure = null)
|
||||||
|
{
|
||||||
|
var fileSystem = RazorProjectFileSystem.Create(targetProjectDirectory);
|
||||||
|
var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder =>
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.SetNamespace(rootNamespace)
|
||||||
|
.SetBaseType("Microsoft.Extensions.RazorViews.BaseView")
|
||||||
|
.ConfigureClass((document, @class) =>
|
||||||
|
{
|
||||||
|
@class.ClassName = Path.GetFileNameWithoutExtension(document.Source.FilePath);
|
||||||
|
@class.Modifiers.Clear();
|
||||||
|
@class.Modifiers.Add("internal");
|
||||||
|
});
|
||||||
|
|
||||||
|
SectionDirective.Register(builder);
|
||||||
|
|
||||||
|
builder.Features.Add(new SuppressChecksumOptionsFeature());
|
||||||
|
builder.Features.Add(new SuppressMetadataAttributesFeature());
|
||||||
|
|
||||||
|
if (configure != null)
|
||||||
|
{
|
||||||
|
configure(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddDefaultImports(@"
|
||||||
|
@using System
|
||||||
|
@using System.Threading.Tasks
|
||||||
|
");
|
||||||
|
});
|
||||||
|
return projectEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IList<RazorPageGeneratorResult> MainCore(RazorProjectEngine projectEngine, string targetProjectDirectory)
|
||||||
|
{
|
||||||
|
var viewDirectories = Directory.EnumerateDirectories(targetProjectDirectory, "Views", SearchOption.AllDirectories);
|
||||||
|
var fileCount = 0;
|
||||||
|
|
||||||
|
var results = new List<RazorPageGeneratorResult>();
|
||||||
|
foreach (var viewDir in viewDirectories)
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine(" Generating code files for views in {0}", viewDir);
|
||||||
|
var viewDirPath = viewDir.Substring(targetProjectDirectory.Length).Replace('\\', '/');
|
||||||
|
var cshtmlFiles = projectEngine.FileSystem.EnumerateItems(viewDirPath);
|
||||||
|
|
||||||
|
if (!cshtmlFiles.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine(" No .cshtml files were found.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in cshtmlFiles)
|
||||||
|
{
|
||||||
|
Console.WriteLine(" Generating code file for view {0}...", item.FileName);
|
||||||
|
results.Add(GenerateCodeFile(projectEngine, item));
|
||||||
|
Console.WriteLine(" Done!");
|
||||||
|
fileCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RazorPageGeneratorResult GenerateCodeFile(RazorProjectEngine projectEngine, RazorProjectItem projectItem)
|
||||||
|
{
|
||||||
|
var projectItemWrapper = new FileSystemRazorProjectItemWrapper(projectItem);
|
||||||
|
var codeDocument = projectEngine.Process(projectItemWrapper);
|
||||||
|
var cSharpDocument = codeDocument.GetCSharpDocument();
|
||||||
|
if (cSharpDocument.Diagnostics.Any())
|
||||||
|
{
|
||||||
|
var diagnostics = string.Join(Environment.NewLine, cSharpDocument.Diagnostics);
|
||||||
|
Console.WriteLine($"One or more parse errors encountered. This will not prevent the generator from continuing: {Environment.NewLine}{diagnostics}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var generatedCodeFilePath = Path.ChangeExtension(projectItem.PhysicalPath, ".Designer.cs");
|
||||||
|
return new RazorPageGeneratorResult
|
||||||
|
{
|
||||||
|
FilePath = generatedCodeFilePath,
|
||||||
|
GeneratedCode = cSharpDocument.GeneratedCode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SuppressChecksumOptionsFeature : RazorEngineFeatureBase, IConfigureRazorCodeGenerationOptionsFeature
|
||||||
|
{
|
||||||
|
public int Order { get; set; }
|
||||||
|
|
||||||
|
public void Configure(RazorCodeGenerationOptionsBuilder options)
|
||||||
|
{
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
options.SuppressChecksum = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SuppressMetadataAttributesFeature : RazorEngineFeatureBase, IConfigureRazorCodeGenerationOptionsFeature
|
||||||
|
{
|
||||||
|
public int Order { get; set; }
|
||||||
|
|
||||||
|
public void Configure(RazorCodeGenerationOptionsBuilder options)
|
||||||
|
{
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
options.SuppressMetadataAttributes = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileSystemRazorProjectItemWrapper : RazorProjectItem
|
||||||
|
{
|
||||||
|
private readonly RazorProjectItem _source;
|
||||||
|
|
||||||
|
public FileSystemRazorProjectItemWrapper(RazorProjectItem item)
|
||||||
|
{
|
||||||
|
_source = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string BasePath => _source.BasePath;
|
||||||
|
|
||||||
|
public override string FilePath => _source.FilePath;
|
||||||
|
|
||||||
|
// Mask the full name since we don't want a developer's local file paths to be commited.
|
||||||
|
public override string PhysicalPath => _source.FileName;
|
||||||
|
|
||||||
|
public override bool Exists => _source.Exists;
|
||||||
|
|
||||||
|
public override Stream Read()
|
||||||
|
{
|
||||||
|
var processedContent = ProcessFileIncludes();
|
||||||
|
return new MemoryStream(Encoding.UTF8.GetBytes(processedContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ProcessFileIncludes()
|
||||||
|
{
|
||||||
|
var basePath = System.IO.Path.GetDirectoryName(_source.PhysicalPath);
|
||||||
|
var cshtmlContent = File.ReadAllText(_source.PhysicalPath);
|
||||||
|
|
||||||
|
var startMatch = "<%$ include: ";
|
||||||
|
var endMatch = " %>";
|
||||||
|
var startIndex = 0;
|
||||||
|
while (startIndex < cshtmlContent.Length)
|
||||||
|
{
|
||||||
|
startIndex = cshtmlContent.IndexOf(startMatch, startIndex);
|
||||||
|
if (startIndex == -1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var endIndex = cshtmlContent.IndexOf(endMatch, startIndex);
|
||||||
|
if (endIndex == -1)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Invalid include file format in {_source.PhysicalPath}. Usage example: <%$ include: ErrorPage.js %>");
|
||||||
|
}
|
||||||
|
var includeFileName = cshtmlContent.Substring(startIndex + startMatch.Length, endIndex - (startIndex + startMatch.Length));
|
||||||
|
Console.WriteLine(" Inlining file {0}", includeFileName);
|
||||||
|
var includeFileContent = File.ReadAllText(System.IO.Path.Combine(basePath, includeFileName));
|
||||||
|
cshtmlContent = cshtmlContent.Substring(0, startIndex) + includeFileContent + cshtmlContent.Substring(endIndex + endMatch.Length);
|
||||||
|
startIndex = startIndex + includeFileContent.Length;
|
||||||
|
}
|
||||||
|
return cshtmlContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Description>Builds Razor pages for views in a project. For internal use only.</Description>
|
||||||
|
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||||
|
<AssemblyName>dotnet-razorpagegenerator</AssemblyName>
|
||||||
|
<PackageId>RazorPageGenerator</PackageId>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<EnableApiCheck>false</EnableApiCheck>
|
||||||
|
<IsShipping>false</IsShipping>
|
||||||
|
<ExcludeFromSourceBuild>true</ExcludeFromSourceBuild>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Razor.Language" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace RazorPageGenerator
|
||||||
|
{
|
||||||
|
public class RazorPageGeneratorResult
|
||||||
|
{
|
||||||
|
public string FilePath { get; set; }
|
||||||
|
|
||||||
|
public string GeneratedCode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -103,6 +103,8 @@ namespace MusicStore
|
||||||
{
|
{
|
||||||
options.AddPolicy("ManageStore", new AuthorizationPolicyBuilder().RequireClaim("ManageStore", "Allowed").Build());
|
options.AddPolicy("ManageStore", new AuthorizationPolicyBuilder().RequireClaim("ManageStore", "Allowed").Build());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app)
|
public void Configure(IApplicationBuilder app)
|
||||||
|
|
@ -123,8 +125,6 @@ namespace MusicStore
|
||||||
// During development use the ErrorPage middleware to display error information in the browser
|
// During development use the ErrorPage middleware to display error information in the browser
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
|
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
|
|
||||||
// Configure Session.
|
// Configure Session.
|
||||||
app.UseSession();
|
app.UseSession();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ namespace MusicStore
|
||||||
options.Scope.Add("wl.signin");
|
options.Scope.Add("wl.signin");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app)
|
public void Configure(IApplicationBuilder app)
|
||||||
|
|
@ -160,8 +161,6 @@ namespace MusicStore
|
||||||
// Note: Not recommended for production.
|
// Note: Not recommended for production.
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
|
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
|
|
||||||
// Configure Session.
|
// Configure Session.
|
||||||
app.UseSession();
|
app.UseSession();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,8 @@ namespace MusicStore
|
||||||
options.ClientId = "000000004012C08A";
|
options.ClientId = "000000004012C08A";
|
||||||
options.ClientSecret = "GaMQ2hCnqAC6EcDLnXsAeBVIJOLmeutL";
|
options.ClientSecret = "GaMQ2hCnqAC6EcDLnXsAeBVIJOLmeutL";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
//This method is invoked when ASPNETCORE_ENVIRONMENT is 'Development' or is not defined
|
//This method is invoked when ASPNETCORE_ENVIRONMENT is 'Development' or is not defined
|
||||||
|
|
@ -132,8 +134,6 @@ namespace MusicStore
|
||||||
// During development use the ErrorPage middleware to display error information in the browser
|
// During development use the ErrorPage middleware to display error information in the browser
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
|
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
|
|
||||||
Configure(app);
|
Configure(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,8 @@ namespace MusicStore
|
||||||
authBuilder.RequireClaim("ManageStore", "Allowed");
|
authBuilder.RequireClaim("ManageStore", "Allowed");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app)
|
public void Configure(IApplicationBuilder app)
|
||||||
|
|
@ -114,7 +116,6 @@ namespace MusicStore
|
||||||
// request pipeline.
|
// request pipeline.
|
||||||
// Note: Not recommended for production.
|
// Note: Not recommended for production.
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
|
|
||||||
app.Use((context, next) =>
|
app.Use((context, next) =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,8 @@ namespace MusicStore
|
||||||
options.ClientId = "[ClientId]";
|
options.ClientId = "[ClientId]";
|
||||||
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
|
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app)
|
public void Configure(IApplicationBuilder app)
|
||||||
|
|
@ -122,8 +124,6 @@ namespace MusicStore
|
||||||
// During development use the ErrorPage middleware to display error information in the browser
|
// During development use the ErrorPage middleware to display error information in the browser
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
|
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
|
|
||||||
// Configure Session.
|
// Configure Session.
|
||||||
app.UseSession();
|
app.UseSession();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ namespace BlazorServerWeb_CSharp
|
||||||
#endif
|
#endif
|
||||||
#if (IndividualLocalAuth)
|
#if (IndividualLocalAuth)
|
||||||
services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
|
services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
#endif
|
#endif
|
||||||
services.AddSingleton<WeatherForecastService>();
|
services.AddSingleton<WeatherForecastService>();
|
||||||
}
|
}
|
||||||
|
|
@ -132,9 +133,6 @@ namespace BlazorServerWeb_CSharp
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
#if (IndividualLocalAuth)
|
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ namespace ComponentsWebAssembly_CSharp.Server
|
||||||
#else
|
#else
|
||||||
options.UseSqlite(
|
options.UseSqlite(
|
||||||
Configuration.GetConnectionString("DefaultConnection")));
|
Configuration.GetConnectionString("DefaultConnection")));
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
||||||
|
|
@ -99,9 +101,6 @@ namespace ComponentsWebAssembly_CSharp.Server
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
#if (IndividualLocalAuth)
|
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
#endif
|
|
||||||
app.UseWebAssemblyDebugging();
|
app.UseWebAssemblyDebugging();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ namespace Company.WebApplication1
|
||||||
options.UseSqlite(
|
options.UseSqlite(
|
||||||
Configuration.GetConnectionString("DefaultConnection")));
|
Configuration.GetConnectionString("DefaultConnection")));
|
||||||
#endif
|
#endif
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
||||||
.AddEntityFrameworkStores<ApplicationDbContext>();
|
.AddEntityFrameworkStores<ApplicationDbContext>();
|
||||||
#elif (OrganizationalAuth)
|
#elif (OrganizationalAuth)
|
||||||
|
|
@ -120,9 +121,6 @@ namespace Company.WebApplication1
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
#if (IndividualLocalAuth)
|
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ namespace Company.WebApplication1
|
||||||
options.UseSqlite(
|
options.UseSqlite(
|
||||||
Configuration.GetConnectionString("DefaultConnection")));
|
Configuration.GetConnectionString("DefaultConnection")));
|
||||||
#endif
|
#endif
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
|
|
||||||
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
||||||
.AddEntityFrameworkStores<ApplicationDbContext>();
|
.AddEntityFrameworkStores<ApplicationDbContext>();
|
||||||
#elif (OrganizationalAuth)
|
#elif (OrganizationalAuth)
|
||||||
|
|
@ -120,9 +122,6 @@ namespace Company.WebApplication1
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
#if (IndividualLocalAuth)
|
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ namespace Company.WebApplication1
|
||||||
#else
|
#else
|
||||||
options.UseSqlite(
|
options.UseSqlite(
|
||||||
Configuration.GetConnectionString("DefaultConnection")));
|
Configuration.GetConnectionString("DefaultConnection")));
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
||||||
|
|
@ -70,9 +72,6 @@ namespace Company.WebApplication1
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
#if (IndividualLocalAuth)
|
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ namespace Company.WebApplication1
|
||||||
#else
|
#else
|
||||||
options.UseSqlite(
|
options.UseSqlite(
|
||||||
Configuration.GetConnectionString("DefaultConnection")));
|
Configuration.GetConnectionString("DefaultConnection")));
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
||||||
|
|
@ -72,9 +74,6 @@ namespace Company.WebApplication1
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
#if (IndividualLocalAuth)
|
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ namespace Identity.ExternalClaims
|
||||||
// Register no-op EmailSender used by account confirmation and password reset during development
|
// Register no-op EmailSender used by account confirmation and password reset during development
|
||||||
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=532713
|
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=532713
|
||||||
services.AddSingleton<IEmailSender, EmailSender>();
|
services.AddSingleton<IEmailSender, EmailSender>();
|
||||||
|
|
||||||
|
services.AddDatabaseDeveloperPageExceptionFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
|
@ -72,7 +74,6 @@ namespace Identity.ExternalClaims
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
app.UseDatabaseErrorPage();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue