diff --git a/DiagnosticsPages.sln b/DiagnosticsPages.sln index f3c669a4f8..bd8e66ac09 100644 --- a/DiagnosticsPages.sln +++ b/DiagnosticsPages.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.22228.0 +VisualStudioVersion = 14.0.22228.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{509A6F36-AD80-4A18-B5B1-717D38DFF29D}" EndProject @@ -28,6 +28,12 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Diagnostic EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ErrorHandlerSample", "samples\ErrorHandlerSample\ErrorHandlerSample.kproj", "{427CDB36-78B0-4583-9EBC-7F283DE60355}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Diagnostics.Entity", "src\Microsoft.AspNet.Diagnostics.Entity\Microsoft.AspNet.Diagnostics.Entity.kproj", "{4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Diagnostics.Entity.Tests", "test\Microsoft.AspNet.Diagnostics.Entity.Tests\Microsoft.AspNet.Diagnostics.Entity.Tests.kproj", "{5486117B-A742-49E0-94FC-12B76F061803}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Diagnostics.Entity.FunctionalTests", "test\Microsoft.AspNet.Diagnostics.Entity.FunctionalTests\Microsoft.AspNet.Diagnostics.Entity.FunctionalTests.kproj", "{2F9B479D-8247-4210-804B-78E6DD5C3E98}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -108,6 +114,42 @@ Global {427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|Mixed Platforms.Build.0 = Release|Any CPU {427CDB36-78B0-4583-9EBC-7F283DE60355}.Release|x86.ActiveCfg = Release|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|x86.ActiveCfg = Debug|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Debug|x86.Build.0 = Debug|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|Any CPU.Build.0 = Release|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|x86.ActiveCfg = Release|Any CPU + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE}.Release|x86.Build.0 = Release|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Debug|x86.ActiveCfg = Debug|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Debug|x86.Build.0 = Debug|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Release|Any CPU.Build.0 = Release|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Release|x86.ActiveCfg = Release|Any CPU + {5486117B-A742-49E0-94FC-12B76F061803}.Release|x86.Build.0 = Release|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Debug|x86.ActiveCfg = Debug|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Debug|x86.Build.0 = Debug|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Release|Any CPU.Build.0 = Release|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Release|x86.ActiveCfg = Release|Any CPU + {2F9B479D-8247-4210-804B-78E6DD5C3E98}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -120,5 +162,8 @@ Global {CD62A191-39F5-4C86-BC1D-7731085120F5} = {ACAA0157-A8C4-4152-93DE-90CCDF304087} {994351B4-7B2A-4139-8B72-72C5BB5CC618} = {2AF90579-B118-4583-AE88-672EFACB5BC4} {427CDB36-78B0-4583-9EBC-7F283DE60355} = {ACAA0157-A8C4-4152-93DE-90CCDF304087} + {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D} + {5486117B-A742-49E0-94FC-12B76F061803} = {2AF90579-B118-4583-AE88-672EFACB5BC4} + {2F9B479D-8247-4210-804B-78E6DD5C3E98} = {2AF90579-B118-4583-AE88-672EFACB5BC4} EndGlobalSection EndGlobal diff --git a/src/Microsoft.AspNet.Diagnostics.Entity/CodeAnnotations.cs b/src/Microsoft.AspNet.Diagnostics.Entity/CodeAnnotations.cs new file mode 100644 index 0000000000..679edd0742 --- /dev/null +++ b/src/Microsoft.AspNet.Diagnostics.Entity/CodeAnnotations.cs @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace JetBrains.Annotations +{ + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | + AttributeTargets.Property | AttributeTargets.Delegate | + AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + internal sealed class NotNullAttribute : Attribute + { + } + + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | + AttributeTargets.Property | AttributeTargets.Delegate | + AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + internal sealed class CanBeNullAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + internal sealed class InvokerParameterNameAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] + internal sealed class NoEnumerationAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] + internal sealed class ContractAnnotationAttribute : Attribute + { + public string Contract { get; private set; } + + public bool ForceFullStates { get; private set; } + + public ContractAnnotationAttribute([NotNull] string contract) + : this(contract, false) + { + } + + public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) + { + Contract = contract; + ForceFullStates = forceFullStates; + } + } + + [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)] + internal sealed class UsedImplicitlyAttribute : Attribute + { + public UsedImplicitlyAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) + { + } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) + { + } + + public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) + { + } + + public UsedImplicitlyAttribute( + ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + public ImplicitUseKindFlags UseKindFlags { get; private set; } + public ImplicitUseTargetFlags TargetFlags { get; private set; } + } + + [Flags] + internal enum ImplicitUseKindFlags + { + Default = Access | Assign | InstantiatedWithFixedConstructorSignature, + Access = 1, + Assign = 2, + InstantiatedWithFixedConstructorSignature = 4, + InstantiatedNoFixedConstructorSignature = 8, + } + + [Flags] + internal enum ImplicitUseTargetFlags + { + Default = Itself, + Itself = 1, + Members = 2, + WithMembers = Itself | Members + } +} + +namespace Microsoft.Data.Entity.Relational.Utilities +{ + internal sealed class ValidatedNotNullAttribute : Attribute + { + } +} diff --git a/src/Microsoft.AspNet.Diagnostics.Entity/DatabaseErrorPageMiddleware.cs b/src/Microsoft.AspNet.Diagnostics.Entity/DatabaseErrorPageMiddleware.cs index bd4ddb6d09..9eebcdd04e 100644 --- a/src/Microsoft.AspNet.Diagnostics.Entity/DatabaseErrorPageMiddleware.cs +++ b/src/Microsoft.AspNet.Diagnostics.Entity/DatabaseErrorPageMiddleware.cs @@ -73,7 +73,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity var dbContext = (DbContext)context.RequestServices.GetService(dbContextType); if (dbContext == null) { - _logger.WriteError(Strings.DatabaseErrorPageMiddleware_ContextNotRegistered(dbContextType.FullName)); + _logger.WriteError(Strings.FormatDatabaseErrorPageMiddleware_ContextNotRegistered(dbContextType.FullName)); } else { diff --git a/src/Microsoft.AspNet.Diagnostics.Entity/MigrationsEndPointMiddleware.cs b/src/Microsoft.AspNet.Diagnostics.Entity/MigrationsEndPointMiddleware.cs index 475174ce9a..e381179d29 100644 --- a/src/Microsoft.AspNet.Diagnostics.Entity/MigrationsEndPointMiddleware.cs +++ b/src/Microsoft.AspNet.Diagnostics.Entity/MigrationsEndPointMiddleware.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity if (context.Request.Path.Equals(_options.Path)) { - _logger.WriteVerbose(Strings.MigrationsEndPointMiddleware_RequestPathMatched(context.Request.Path)); + _logger.WriteVerbose(Strings.FormatMigrationsEndPointMiddleware_RequestPathMatched(context.Request.Path)); using (RequestServicesContainer.EnsureRequestServices(context, _serviceProvider)) { @@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity { try { - _logger.WriteVerbose(Strings.MigrationsEndPointMiddleware_ApplyingMigrations(db.GetType().FullName)); + _logger.WriteVerbose(Strings.FormatMigrationsEndPointMiddleware_ApplyingMigrations(db.GetType().FullName)); db.Database.AsMigrationsEnabled().ApplyMigrations(); @@ -59,11 +59,11 @@ namespace Microsoft.AspNet.Diagnostics.Entity context.Response.Headers.Add("Pragma", new[] { "no-cache" }); context.Response.Headers.Add("Cache-Control", new[] { "no-cache" }); - _logger.WriteVerbose(Strings.MigrationsEndPointMiddleware_Applied(db.GetType().FullName)); + _logger.WriteVerbose(Strings.FormatMigrationsEndPointMiddleware_Applied(db.GetType().FullName)); } catch (Exception ex) { - var message = Strings.MigrationsEndPointMiddleware_Exception(db.GetType().FullName); + var message = Strings.FormatMigrationsEndPointMiddleware_Exception(db.GetType().FullName); _logger.WriteError(message); throw new InvalidOperationException(message, ex); } @@ -90,7 +90,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity var contextType = Type.GetType(contextTypeName); if (contextType == null) { - var message = Strings.MigrationsEndPointMiddleware_InvalidContextType(contextTypeName); + var message = Strings.FormatMigrationsEndPointMiddleware_InvalidContextType(contextTypeName); logger.WriteError(message); await WriteErrorToResponse(context.Response, message).WithCurrentCulture(); return null; @@ -99,7 +99,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity var db = (DbContext)context.RequestServices.GetService(contextType); if (db == null) { - var message = Strings.MigrationsEndPointMiddleware_ContextNotRegistered(contextType.FullName); + var message = Strings.FormatMigrationsEndPointMiddleware_ContextNotRegistered(contextType.FullName); logger.WriteError(message); await WriteErrorToResponse(context.Response, message).WithCurrentCulture(); return null; diff --git a/src/Microsoft.AspNet.Diagnostics.Entity/Properties/Strings.Designer.cs b/src/Microsoft.AspNet.Diagnostics.Entity/Properties/Strings.Designer.cs index 28d70ca160..01ed143a61 100644 --- a/src/Microsoft.AspNet.Diagnostics.Entity/Properties/Strings.Designer.cs +++ b/src/Microsoft.AspNet.Diagnostics.Entity/Properties/Strings.Designer.cs @@ -1,13 +1,11 @@ // namespace Microsoft.AspNet.Diagnostics.Entity { - using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Resources; - using JetBrains.Annotations; - public static class Strings + internal static class Strings { private static readonly ResourceManager _resourceManager = new ResourceManager("Microsoft.AspNet.Diagnostics.Entity.Strings", typeof(Strings).GetTypeInfo().Assembly); @@ -15,7 +13,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// The string argument '{argumentName}' cannot be empty. /// - public static string ArgumentIsEmpty([CanBeNull] object argumentName) + internal static string ArgumentIsEmpty + { + get { return GetString("ArgumentIsEmpty"); } + } + + /// + /// The string argument '{argumentName}' cannot be empty. + /// + internal static string FormatArgumentIsEmpty(object argumentName) { return string.Format(CultureInfo.CurrentCulture, GetString("ArgumentIsEmpty", "argumentName"), argumentName); } @@ -23,7 +29,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// The collection argument '{argumentName}' must contain at least one element. /// - public static string CollectionArgumentIsEmpty([CanBeNull] object argumentName) + internal static string CollectionArgumentIsEmpty + { + get { return GetString("CollectionArgumentIsEmpty"); } + } + + /// + /// The collection argument '{argumentName}' must contain at least one element. + /// + internal static string FormatCollectionArgumentIsEmpty(object argumentName) { return string.Format(CultureInfo.CurrentCulture, GetString("CollectionArgumentIsEmpty", "argumentName"), argumentName); } @@ -31,7 +45,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// 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. Skipping display of the database error page. /// - public static string DatabaseErrorPageMiddleware_ContextNotRegistered([CanBeNull] object p0) + internal static string DatabaseErrorPageMiddleware_ContextNotRegistered + { + get { return GetString("DatabaseErrorPageMiddleware_ContextNotRegistered"); } + } + + /// + /// 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. Skipping display of the database error page. + /// + internal static string FormatDatabaseErrorPageMiddleware_ContextNotRegistered(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("DatabaseErrorPageMiddleware_ContextNotRegistered"), p0); } @@ -39,79 +61,159 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// An exception occurred while calculating the database error page content. Skipping display of the database error page. /// - public static string DatabaseErrorPageMiddleware_Exception + internal static string DatabaseErrorPageMiddleware_Exception { get { return GetString("DatabaseErrorPageMiddleware_Exception"); } } + /// + /// An exception occurred while calculating the database error page content. Skipping display of the database error page. + /// + internal static string FormatDatabaseErrorPageMiddleware_Exception() + { + return GetString("DatabaseErrorPageMiddleware_Exception"); + } + /// /// > k ef migration add [migration name] /// - public static string DatabaseErrorPage_AddMigrationCommand + internal static string DatabaseErrorPage_AddMigrationCommand { get { return GetString("DatabaseErrorPage_AddMigrationCommand"); } } + /// + /// > k ef migration add [migration name] + /// + internal static string FormatDatabaseErrorPage_AddMigrationCommand() + { + return GetString("DatabaseErrorPage_AddMigrationCommand"); + } + /// /// Apply Migrations /// - public static string DatabaseErrorPage_ApplyMigrationsButton + internal static string DatabaseErrorPage_ApplyMigrationsButton { get { return GetString("DatabaseErrorPage_ApplyMigrationsButton"); } } + /// + /// Apply Migrations + /// + internal static string FormatDatabaseErrorPage_ApplyMigrationsButton() + { + return GetString("DatabaseErrorPage_ApplyMigrationsButton"); + } + /// /// Migrations Applied /// - public static string DatabaseErrorPage_ApplyMigrationsButtonDone + internal static string DatabaseErrorPage_ApplyMigrationsButtonDone { get { return GetString("DatabaseErrorPage_ApplyMigrationsButtonDone"); } } + /// + /// Migrations Applied + /// + internal static string FormatDatabaseErrorPage_ApplyMigrationsButtonDone() + { + return GetString("DatabaseErrorPage_ApplyMigrationsButtonDone"); + } + /// /// Applying Migrations... /// - public static string DatabaseErrorPage_ApplyMigrationsButtonRunning + internal static string DatabaseErrorPage_ApplyMigrationsButtonRunning { get { return GetString("DatabaseErrorPage_ApplyMigrationsButtonRunning"); } } + /// + /// Applying Migrations... + /// + internal static string FormatDatabaseErrorPage_ApplyMigrationsButtonRunning() + { + return GetString("DatabaseErrorPage_ApplyMigrationsButtonRunning"); + } + /// /// An error occurred applying migrations, try applying them from the command line /// - public static string DatabaseErrorPage_ApplyMigrationsFailed + internal static string DatabaseErrorPage_ApplyMigrationsFailed { get { return GetString("DatabaseErrorPage_ApplyMigrationsFailed"); } } + /// + /// An error occurred applying migrations, try applying them from the command line + /// + internal static string FormatDatabaseErrorPage_ApplyMigrationsFailed() + { + return GetString("DatabaseErrorPage_ApplyMigrationsFailed"); + } + /// /// You can also apply migrations from the command line: /// - public static string DatabaseErrorPage_HowToApplyFromCmd + internal static string DatabaseErrorPage_HowToApplyFromCmd { get { return GetString("DatabaseErrorPage_HowToApplyFromCmd"); } } + /// + /// You can also apply migrations from the command line: + /// + internal static string FormatDatabaseErrorPage_HowToApplyFromCmd() + { + return GetString("DatabaseErrorPage_HowToApplyFromCmd"); + } + /// /// Try refreshing the page /// - public static string DatabaseErrorPage_MigrationsAppliedRefresh + internal static string DatabaseErrorPage_MigrationsAppliedRefresh { get { return GetString("DatabaseErrorPage_MigrationsAppliedRefresh"); } } + /// + /// Try refreshing the page + /// + internal static string FormatDatabaseErrorPage_MigrationsAppliedRefresh() + { + return GetString("DatabaseErrorPage_MigrationsAppliedRefresh"); + } + /// /// From the command line, scaffold a new migration and apply it to the database: /// - public static string DatabaseErrorPage_NoDbOrMigrationsInfo + internal static string DatabaseErrorPage_NoDbOrMigrationsInfo { get { return GetString("DatabaseErrorPage_NoDbOrMigrationsInfo"); } } + /// + /// From the command line, scaffold a new migration and apply it to the database: + /// + internal static string FormatDatabaseErrorPage_NoDbOrMigrationsInfo() + { + return GetString("DatabaseErrorPage_NoDbOrMigrationsInfo"); + } + /// /// Use migrations to create the database for {0} /// - public static string DatabaseErrorPage_NoDbOrMigrationsTitle([CanBeNull] object p0) + internal static string DatabaseErrorPage_NoDbOrMigrationsTitle + { + get { return GetString("DatabaseErrorPage_NoDbOrMigrationsTitle"); } + } + + /// + /// Use migrations to create the database for {0} + /// + internal static string FormatDatabaseErrorPage_NoDbOrMigrationsTitle(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("DatabaseErrorPage_NoDbOrMigrationsTitle"), p0); } @@ -119,15 +221,31 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// Scaffold a new migration for these changes and apply them to the database from the command line: /// - public static string DatabaseErrorPage_PendingChangesInfo + internal static string DatabaseErrorPage_PendingChangesInfo { get { return GetString("DatabaseErrorPage_PendingChangesInfo"); } } + /// + /// Scaffold a new migration for these changes and apply them to the database from the command line: + /// + internal static string FormatDatabaseErrorPage_PendingChangesInfo() + { + return GetString("DatabaseErrorPage_PendingChangesInfo"); + } + /// /// There are pending model changes for {0} /// - public static string DatabaseErrorPage_PendingChangesTitle([CanBeNull] object p0) + internal static string DatabaseErrorPage_PendingChangesTitle + { + get { return GetString("DatabaseErrorPage_PendingChangesTitle"); } + } + + /// + /// There are pending model changes for {0} + /// + internal static string FormatDatabaseErrorPage_PendingChangesTitle(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("DatabaseErrorPage_PendingChangesTitle"), p0); } @@ -135,7 +253,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// There are migrations for {0} that have not been applied to the database /// - public static string DatabaseErrorPage_PendingMigrationsInfo([CanBeNull] object p0) + internal static string DatabaseErrorPage_PendingMigrationsInfo + { + get { return GetString("DatabaseErrorPage_PendingMigrationsInfo"); } + } + + /// + /// There are migrations for {0} that have not been applied to the database + /// + internal static string FormatDatabaseErrorPage_PendingMigrationsInfo(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("DatabaseErrorPage_PendingMigrationsInfo"), p0); } @@ -143,7 +269,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// Applying existing migrations for {0} may resolve this issue /// - public static string DatabaseErrorPage_PendingMigrationsTitle([CanBeNull] object p0) + internal static string DatabaseErrorPage_PendingMigrationsTitle + { + get { return GetString("DatabaseErrorPage_PendingMigrationsTitle"); } + } + + /// + /// Applying existing migrations for {0} may resolve this issue + /// + internal static string FormatDatabaseErrorPage_PendingMigrationsTitle(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("DatabaseErrorPage_PendingMigrationsTitle"), p0); } @@ -151,15 +285,31 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// > k ef migration apply /// - public static string DatabaseErrorPage_ApplyMigrationsCommand + internal static string DatabaseErrorPage_ApplyMigrationsCommand { get { return GetString("DatabaseErrorPage_ApplyMigrationsCommand"); } } + /// + /// > k ef migration apply + /// + internal static string FormatDatabaseErrorPage_ApplyMigrationsCommand() + { + return GetString("DatabaseErrorPage_ApplyMigrationsCommand"); + } + /// /// The value provided for argument '{argumentName}' must be a valid value of enum type '{enumType}'. /// - public static string InvalidEnumValue([CanBeNull] object argumentName, [CanBeNull] object enumType) + internal static string InvalidEnumValue + { + get { return GetString("InvalidEnumValue"); } + } + + /// + /// The value provided for argument '{argumentName}' must be a valid value of enum type '{enumType}'. + /// + internal static string FormatInvalidEnumValue(object argumentName, object enumType) { return string.Format(CultureInfo.CurrentCulture, GetString("InvalidEnumValue", "argumentName", "enumType"), argumentName, enumType); } @@ -167,7 +317,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// Migrations successfully applied for context '{0}'. /// - public static string MigrationsEndPointMiddleware_Applied([CanBeNull] object p0) + internal static string MigrationsEndPointMiddleware_Applied + { + get { return GetString("MigrationsEndPointMiddleware_Applied"); } + } + + /// + /// Migrations successfully applied for context '{0}'. + /// + internal static string FormatMigrationsEndPointMiddleware_Applied(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("MigrationsEndPointMiddleware_Applied"), p0); } @@ -175,7 +333,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// Request is valid, applying migrations for context '{0}'. /// - public static string MigrationsEndPointMiddleware_ApplyingMigrations([CanBeNull] object p0) + internal static string MigrationsEndPointMiddleware_ApplyingMigrations + { + get { return GetString("MigrationsEndPointMiddleware_ApplyingMigrations"); } + } + + /// + /// Request is valid, applying migrations for context '{0}'. + /// + internal static string FormatMigrationsEndPointMiddleware_ApplyingMigrations(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("MigrationsEndPointMiddleware_ApplyingMigrations"), p0); } @@ -183,7 +349,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// 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. /// - public static string MigrationsEndPointMiddleware_ContextNotRegistered([CanBeNull] object p0) + internal static string MigrationsEndPointMiddleware_ContextNotRegistered + { + get { return GetString("MigrationsEndPointMiddleware_ContextNotRegistered"); } + } + + /// + /// 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. + /// + internal static string FormatMigrationsEndPointMiddleware_ContextNotRegistered(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("MigrationsEndPointMiddleware_ContextNotRegistered"), p0); } @@ -191,7 +365,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// An error occurred while applying the migrations for '{0}'. See InnerException for details. /// - public static string MigrationsEndPointMiddleware_Exception([CanBeNull] object p0) + internal static string MigrationsEndPointMiddleware_Exception + { + get { return GetString("MigrationsEndPointMiddleware_Exception"); } + } + + /// + /// An error occurred while applying the migrations for '{0}'. See InnerException for details. + /// + internal static string FormatMigrationsEndPointMiddleware_Exception(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("MigrationsEndPointMiddleware_Exception"), p0); } @@ -199,7 +381,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// 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. /// - public static string MigrationsEndPointMiddleware_InvalidContextType([CanBeNull] object p0) + internal static string MigrationsEndPointMiddleware_InvalidContextType + { + get { return GetString("MigrationsEndPointMiddleware_InvalidContextType"); } + } + + /// + /// 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. + /// + internal static string FormatMigrationsEndPointMiddleware_InvalidContextType(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("MigrationsEndPointMiddleware_InvalidContextType"), p0); } @@ -207,15 +397,31 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// No context type was specified. Ensure the form data from the request includes a contextTypeName value, specifying the context to apply migrations for. /// - public static string MigrationsEndPointMiddleware_NoContextType + internal static string MigrationsEndPointMiddleware_NoContextType { get { return GetString("MigrationsEndPointMiddleware_NoContextType"); } } + /// + /// No context type was specified. Ensure the form data from the request includes a contextTypeName value, specifying the context to apply migrations for. + /// + internal static string FormatMigrationsEndPointMiddleware_NoContextType() + { + return GetString("MigrationsEndPointMiddleware_NoContextType"); + } + /// /// Request path matched the path configured for this migrations endpoint ({0}). Attempting to process the migrations request. /// - public static string MigrationsEndPointMiddleware_RequestPathMatched([CanBeNull] object p0) + internal static string MigrationsEndPointMiddleware_RequestPathMatched + { + get { return GetString("MigrationsEndPointMiddleware_RequestPathMatched"); } + } + + /// + /// Request path matched the path configured for this migrations endpoint ({0}). Attempting to process the migrations request. + /// + internal static string FormatMigrationsEndPointMiddleware_RequestPathMatched(object p0) { return string.Format(CultureInfo.CurrentCulture, GetString("MigrationsEndPointMiddleware_RequestPathMatched"), p0); } @@ -223,24 +429,40 @@ namespace Microsoft.AspNet.Diagnostics.Entity /// /// A database operation failed while processing the request. /// - public static string DatabaseErrorPage_Title + internal static string DatabaseErrorPage_Title { get { return GetString("DatabaseErrorPage_Title"); } } + /// + /// A database operation failed while processing the request. + /// + internal static string FormatDatabaseErrorPage_Title() + { + return GetString("DatabaseErrorPage_Title"); + } + /// /// To use migrations from a command prompt you will need to <a href='http://go.microsoft.com/fwlink/?LinkId=518242'>install K Version Manager (KVM)</a>. Once installed, you can run migration commands from a standard command prompt in the project directory. /// - public static string DatabaseErrorPage_EnableMigrationsCommandsInfo + internal static string DatabaseErrorPage_EnableMigrationsCommandsInfo { get { return GetString("DatabaseErrorPage_EnableMigrationsCommandsInfo"); } } + /// + /// To use migrations from a command prompt you will need to <a href='http://go.microsoft.com/fwlink/?LinkId=518242'>install K Version Manager (KVM)</a>. Once installed, you can run migration commands from a standard command prompt in the project directory. + /// + internal static string FormatDatabaseErrorPage_EnableMigrationsCommandsInfo() + { + return GetString("DatabaseErrorPage_EnableMigrationsCommandsInfo"); + } + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); - Debug.Assert(value != null); + System.Diagnostics.Debug.Assert(value != null); if (formatterNames != null) { diff --git a/src/Microsoft.AspNet.Diagnostics.Entity/Properties/Strings.resx b/src/Microsoft.AspNet.Diagnostics.Entity/Strings.resx similarity index 100% rename from src/Microsoft.AspNet.Diagnostics.Entity/Properties/Strings.resx rename to src/Microsoft.AspNet.Diagnostics.Entity/Strings.resx diff --git a/src/Microsoft.AspNet.Diagnostics.Entity/Utilities/Check.cs b/src/Microsoft.AspNet.Diagnostics.Entity/Utilities/Check.cs index b0fc36be5c..6ba0acffa3 100644 --- a/src/Microsoft.AspNet.Diagnostics.Entity/Utilities/Check.cs +++ b/src/Microsoft.AspNet.Diagnostics.Entity/Utilities/Check.cs @@ -32,7 +32,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Utilities if (value.Count == 0) { - throw new ArgumentException(Strings.CollectionArgumentIsEmpty(parameterName)); + throw new ArgumentException(Strings.FormatCollectionArgumentIsEmpty(parameterName)); } return value; @@ -48,7 +48,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Utilities if (parameterName.Length == 0) { - throw new ArgumentException(Strings.ArgumentIsEmpty("parameterName")); + throw new ArgumentException(Strings.FormatArgumentIsEmpty("parameterName")); } if (ReferenceEquals(value, null)) @@ -58,7 +58,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Utilities if (value.Length == 0) { - throw new ArgumentException(Strings.ArgumentIsEmpty(parameterName)); + throw new ArgumentException(Strings.FormatArgumentIsEmpty(parameterName)); } return value; @@ -71,7 +71,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Utilities if (!Enum.IsDefined(typeof(T), value)) { - throw new ArgumentException(Strings.InvalidEnumValue(parameterName, typeof(T))); + throw new ArgumentException(Strings.FormatInvalidEnumValue(parameterName, typeof(T))); } return value; diff --git a/src/Microsoft.AspNet.Diagnostics.Entity/Views/DatabaseErrorPage.cs b/src/Microsoft.AspNet.Diagnostics.Entity/Views/DatabaseErrorPage.cs index d2cbf854f5..2c14bd0011 100644 --- a/src/Microsoft.AspNet.Diagnostics.Entity/Views/DatabaseErrorPage.cs +++ b/src/Microsoft.AspNet.Diagnostics.Entity/Views/DatabaseErrorPage.cs @@ -159,7 +159,7 @@ using Microsoft.AspNet.Diagnostics.Entity.Views WriteLiteral("

"); #line 56 "DatabaseErrorPage.cshtml" - Write(Strings.DatabaseErrorPage_NoDbOrMigrationsTitle(Model.ContextType.Name)); + Write(Strings.FormatDatabaseErrorPage_NoDbOrMigrationsTitle(Model.ContextType.Name)); #line default #line hidden @@ -198,13 +198,13 @@ using Microsoft.AspNet.Diagnostics.Entity.Views WriteLiteral("
\r\n

"); #line 67 "DatabaseErrorPage.cshtml" - Write(Strings.DatabaseErrorPage_PendingMigrationsTitle(Model.ContextType.Name)); + Write(Strings.FormatDatabaseErrorPage_PendingMigrationsTitle(Model.ContextType.Name)); #line default #line hidden WriteLiteral("

\r\n

"); #line 68 "DatabaseErrorPage.cshtml" - Write(Strings.DatabaseErrorPage_PendingMigrationsInfo(Model.ContextType.Name)); + Write(Strings.FormatDatabaseErrorPage_PendingMigrationsInfo(Model.ContextType.Name)); #line default #line hidden @@ -387,7 +387,7 @@ using Microsoft.AspNet.Diagnostics.Entity.Views WriteLiteral("

\r\n

"); #line 133 "DatabaseErrorPage.cshtml" - Write(Strings.DatabaseErrorPage_PendingChangesTitle(Model.ContextType.Name)); + Write(Strings.FormatDatabaseErrorPage_PendingChangesTitle(Model.ContextType.Name)); #line default #line hidden diff --git a/src/Microsoft.AspNet.Diagnostics.Entity/Views/DatabaseErrorPage.cshtml b/src/Microsoft.AspNet.Diagnostics.Entity/Views/DatabaseErrorPage.cshtml index d559023e5d..9f32ce799b 100644 --- a/src/Microsoft.AspNet.Diagnostics.Entity/Views/DatabaseErrorPage.cshtml +++ b/src/Microsoft.AspNet.Diagnostics.Entity/Views/DatabaseErrorPage.cshtml @@ -53,7 +53,7 @@ @if (!Model.DatabaseExists && !Model.PendingMigrations.Any()) { -

@Strings.DatabaseErrorPage_NoDbOrMigrationsTitle(Model.ContextType.Name)

+

@Strings.FormatDatabaseErrorPage_NoDbOrMigrationsTitle(Model.ContextType.Name)

@Strings.DatabaseErrorPage_NoDbOrMigrationsInfo

@Strings.DatabaseErrorPage_AddMigrationCommand
@@ -64,8 +64,8 @@ else if (Model.PendingMigrations.Any()) {
-

@Strings.DatabaseErrorPage_PendingMigrationsTitle(Model.ContextType.Name)

-

@Strings.DatabaseErrorPage_PendingMigrationsInfo(Model.ContextType.Name)

+

@Strings.FormatDatabaseErrorPage_PendingMigrationsTitle(Model.ContextType.Name)

+

@Strings.FormatDatabaseErrorPage_PendingMigrationsInfo(Model.ContextType.Name)

@if (Model.Options.ListMigrations) { @@ -130,7 +130,7 @@ else if (Model.PendingModelChanges) {
-

@Strings.DatabaseErrorPage_PendingChangesTitle(Model.ContextType.Name)

+

@Strings.FormatDatabaseErrorPage_PendingChangesTitle(Model.ContextType.Name)

@Strings.DatabaseErrorPage_PendingChangesInfo

@Strings.DatabaseErrorPage_AddMigrationCommand
diff --git a/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/DatabaseErrorPageMiddlewareTest.cs b/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/DatabaseErrorPageMiddlewareTest.cs index 23c0cc1ac4..cbd419e705 100644 --- a/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/DatabaseErrorPageMiddlewareTest.cs +++ b/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/DatabaseErrorPageMiddlewareTest.cs @@ -14,10 +14,10 @@ using Microsoft.AspNet.Http; using Microsoft.AspNet.TestHost; using Microsoft.Data.Entity; using Microsoft.Data.Entity.Migrations.Infrastructure; -using Microsoft.Data.Entity.SqlServer.FunctionalTests; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.Logging; using Xunit; +using Microsoft.AspNet.Diagnostics.Entity.Tests.Helpers; namespace Microsoft.AspNet.Diagnostics.Entity.Tests { @@ -75,14 +75,14 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests [Fact] public async Task Error_page_displayed_no_migrations() { - TestServer server = await SetupTestServer(); + TestServer server = SetupTestServer(); HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/"); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); - Assert.Contains(Strings.DatabaseErrorPage_NoDbOrMigrationsTitle(typeof(BloggingContext).Name), content); - Assert.Contains(Strings.DatabaseErrorPage_AddMigrationCommand.Replace(">", ">"), content); - Assert.Contains(Strings.DatabaseErrorPage_ApplyMigrationsCommand.Replace(">", ">"), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", typeof(BloggingContext).Name), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_AddMigrationCommand").Replace(">", ">"), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_ApplyMigrationsCommand").Replace(">", ">"), content); } class NoMigrationsMiddleware @@ -104,18 +104,18 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests [Fact] public async Task Error_page_displayed_pending_migrations() { - TestServer server = await SetupTestServer(); + TestServer server = SetupTestServer(); HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/"); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); - Assert.Contains(Strings.DatabaseErrorPage_PendingMigrationsTitle(typeof(BloggingContextWithMigrations).Name), content); - Assert.Contains(Strings.DatabaseErrorPage_ApplyMigrationsCommand.Replace(">", ">"), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingMigrationsTitle", typeof(BloggingContextWithMigrations).Name), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_ApplyMigrationsCommand").Replace(">", ">"), content); Assert.Contains("
  • 111111111111111_MigrationOne
  • ", content); Assert.Contains("
  • 222222222222222_MigrationTwo
  • ", content); - Assert.DoesNotContain(Strings.DatabaseErrorPage_AddMigrationCommand.Replace(">", ">"), content); + Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_AddMigrationCommand").Replace(">", ">"), content); } class PendingMigrationsMiddleware @@ -137,15 +137,15 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests [Fact] public async Task Error_page_displayed_pending_model_changes() { - TestServer server = await SetupTestServer(); + TestServer server = SetupTestServer(); HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/"); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); - Assert.Contains(Strings.DatabaseErrorPage_PendingChangesTitle(typeof(BloggingContextWithPendingModelChanges).Name), content); - Assert.Contains(Strings.DatabaseErrorPage_AddMigrationCommand.Replace(">", ">"), content); - Assert.Contains(Strings.DatabaseErrorPage_ApplyMigrationsCommand.Replace(">", ">"), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingChangesTitle", typeof(BloggingContextWithPendingModelChanges).Name), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_AddMigrationCommand").Replace(">", ">"), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_ApplyMigrationsCommand").Replace(">", ">"), content); } class PendingModelChangesMiddleware @@ -170,7 +170,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests [Fact] public async Task Error_page_then_apply_migrations() { - TestServer server = await SetupTestServer(); + TestServer server = SetupTestServer(); var client = server.CreateClient(); var expectedMigrationsEndpoint = "/ApplyDatabaseMigrations"; @@ -223,7 +223,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests { var migrationsEndpoint = "/MyCustomEndPoints/ApplyMyMigrationsHere"; - using (var database = await SqlServerTestStore.CreateScratchAsync(createDatabase: false)) + using (var database = SqlServerTestStore.CreateScratch()) { var server = TestServer.Create(app => { @@ -231,7 +231,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests { services.AddEntityFramework().AddSqlServer(); services.AddScoped(); - services.AddInstance(new DbContextOptions().UseSqlServer(database.Connection.ConnectionString)); + services.AddInstance(new DbContextOptions().UseSqlServer(database.ConnectionString)); }); var options = DatabaseErrorPageOptions.ShowAll; @@ -253,7 +253,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests [Fact] public async Task Pass_thru_when_context_not_in_services() { - using (var database = await SqlServerTestStore.CreateScratchAsync(createDatabase: false)) + using (var database = SqlServerTestStore.CreateScratch()) { var logProvider = new TestLoggerProvider(); @@ -266,7 +266,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests services.AddInstance( new DbContextOptions() - .UseSqlServer(database.Connection.ConnectionString)); + .UseSqlServer(database.ConnectionString)); }); app.UseDatabaseErrorPage(); @@ -280,7 +280,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests await server.CreateClient().GetAsync("http://localhost/")); Assert.True(logProvider.Logger.Messages.Any(m => - m.StartsWith(Strings.DatabaseErrorPageMiddleware_ContextNotRegistered(typeof(BloggingContext))))); + m.StartsWith(StringsHelpers.GetResourceString("FormatDatabaseErrorPageMiddleware_ContextNotRegistered", typeof(BloggingContext))))); } } @@ -304,17 +304,17 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests [Fact] public async Task Pass_thru_when_exception_in_logic() { - using (var database = await SqlServerTestStore.CreateScratchAsync(createDatabase: false)) + using (var database = SqlServerTestStore.CreateScratch()) { var logProvider = new TestLoggerProvider(); - var server = await SetupTestServer(logProvider); + var server = SetupTestServer(logProvider); var ex = await Assert.ThrowsAsync(async () => await server.CreateClient().GetAsync("http://localhost/")); Assert.True(logProvider.Logger.Messages.Any(m => - m.StartsWith(Strings.DatabaseErrorPageMiddleware_Exception))); + m.StartsWith(StringsHelpers.GetResourceString("FormatDatabaseErrorPageMiddleware_Exception")))); } } @@ -334,10 +334,10 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests } } - private static async Task SetupTestServer(ILoggerProvider logProvider = null) + private static TestServer SetupTestServer(ILoggerProvider logProvider = null) where TContext : DbContext { - using (var database = await SqlServerTestStore.CreateScratchAsync(createDatabase: false)) + using (var database = SqlServerTestStore.CreateScratch()) { return TestServer.Create(app => { @@ -349,7 +349,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests services.AddScoped(); services.AddInstance( new DbContextOptions() - .UseSqlServer(database.Connection.ConnectionString)); + .UseSqlServer(database.ConnectionString)); }); app.UseDatabaseErrorPage(); diff --git a/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/MigrationsEndPointMiddlewareTest.cs b/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/MigrationsEndPointMiddlewareTest.cs index 8c857030ef..9a60189923 100644 --- a/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/MigrationsEndPointMiddlewareTest.cs +++ b/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/MigrationsEndPointMiddlewareTest.cs @@ -13,9 +13,9 @@ using Microsoft.AspNet.TestHost; using Microsoft.Data.Entity; using Microsoft.Data.Entity.Migrations.Infrastructure; using Microsoft.Data.Entity.Migrations.Utilities; -using Microsoft.Data.Entity.SqlServer.FunctionalTests; using Microsoft.Framework.DependencyInjection; using Xunit; +using Microsoft.AspNet.Diagnostics.Entity.Tests.Helpers; namespace Microsoft.AspNet.Diagnostics.Entity.Tests { @@ -60,9 +60,9 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests private async Task Migration_request(bool useCustomPath) { - using (var database = await SqlServerTestStore.CreateScratchAsync(createDatabase: false)) + using (var database = SqlServerTestStore.CreateScratch()) { - var options = new DbContextOptions().UseSqlServer(database.Connection.ConnectionString); + var options = new DbContextOptions().UseSqlServer(database.ConnectionString); var path = useCustomPath ? new PathString("/EndPoints/ApplyMyMigrations") : MigrationsEndPointOptions.DefaultPath; TestServer server = TestServer.Create(app => @@ -122,7 +122,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests var content = await response.Content.ReadAsStringAsync(); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - Assert.StartsWith(Strings.MigrationsEndPointMiddleware_NoContextType, content); + Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_NoContextType"), content); Assert.True(content.Length > 512); } @@ -144,7 +144,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests var content = await response.Content.ReadAsStringAsync(); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - Assert.StartsWith(Strings.MigrationsEndPointMiddleware_InvalidContextType(typeName), content); + Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_InvalidContextType", typeName), content); Assert.True(content.Length > 512); } @@ -169,16 +169,16 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests var content = await response.Content.ReadAsStringAsync(); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - Assert.StartsWith(Strings.MigrationsEndPointMiddleware_ContextNotRegistered(typeof(BloggingContext)), content); + Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_ContextNotRegistered", typeof(BloggingContext)), content); Assert.True(content.Length > 512); } [Fact] public async Task Exception_while_applying_migrations() { - using (var database = await SqlServerTestStore.CreateScratchAsync(createDatabase: false)) + using (var database = SqlServerTestStore.CreateScratch()) { - var options = new DbContextOptions().UseSqlServer(database.Connection.ConnectionString); + var options = new DbContextOptions().UseSqlServer(database.ConnectionString); TestServer server = TestServer.Create(app => { @@ -200,7 +200,7 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests var ex = await Assert.ThrowsAsync(async () => await server.CreateClient().PostAsync("http://localhost" + MigrationsEndPointOptions.DefaultPath, formData)); - Assert.Equal(Strings.MigrationsEndPointMiddleware_Exception(typeof(BloggingContextWithSnapshotThatThrows)), ex.Message); + Assert.Equal(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_Exception", typeof(BloggingContextWithSnapshotThatThrows)), ex.Message); Assert.Equal("Welcome to the invalid snapshot!", ex.InnerException.Message); } } diff --git a/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/SqlServerTestStore.cs b/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/SqlServerTestStore.cs new file mode 100644 index 0000000000..d4752ab46f --- /dev/null +++ b/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/SqlServerTestStore.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.SqlClient; +using System.Threading; +using Microsoft.Data.Entity; + +namespace Microsoft.AspNet.Diagnostics.Entity.Tests +{ + public class SqlServerTestStore : IDisposable + { + private static int _scratchCount; + + public static SqlServerTestStore CreateScratch() + { + var name = "Microsoft.AspNet.Diagnostics.Entity.FunctionalTests.Scratch_" + Interlocked.Increment(ref _scratchCount); + var db = new SqlServerTestStore(name); + db.EnsureDeleted(); + return db; + } + + private readonly string _connectionString; + + private SqlServerTestStore(string name) + { + _connectionString = new SqlConnectionStringBuilder + { + DataSource = @"(localdb)\v11.0", + InitialCatalog = name, + IntegratedSecurity = true, + ConnectTimeout = 30 + }.ConnectionString; ; + } + + public string ConnectionString + { + get { return _connectionString; } + } + + private void EnsureDeleted() + { + using (var db = new DbContext(new DbContextOptions().UseSqlServer(_connectionString))) + { + db.Database.EnsureDeleted(); + } + } + + public virtual void Dispose() + { + EnsureDeleted(); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/TestModels/BloggingContext.cs b/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/TestModels/BloggingContext.cs index 7d13248bac..a8ecc378aa 100644 --- a/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/TestModels/BloggingContext.cs +++ b/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/TestModels/BloggingContext.cs @@ -3,7 +3,6 @@ using Microsoft.Data.Entity; using Microsoft.Data.Entity.Migrations.Infrastructure; -using Microsoft.Data.Entity.SqlServer.FunctionalTests; using System; using System.Linq; using System.Reflection; diff --git a/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/project.json b/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/project.json index 649018fad3..a064bdbca8 100644 --- a/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/project.json +++ b/test/Microsoft.AspNet.Diagnostics.Entity.FunctionalTests/project.json @@ -1,7 +1,6 @@ { "dependencies": { "EntityFramework.SqlServer": "7.0.0-*", - "EntityFramework.SqlServer.FunctionalTests": "1.0.0", "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-*", "Microsoft.AspNet.Diagnostics.Entity.Tests": "1.0.0", "Microsoft.AspNet.TestHost": "1.0.0-*", diff --git a/test/Microsoft.AspNet.Diagnostics.Entity.Tests/ApiConsistencyTestBase.cs b/test/Microsoft.AspNet.Diagnostics.Entity.Tests/ApiConsistencyTestBase.cs new file mode 100644 index 0000000000..135add6c98 --- /dev/null +++ b/test/Microsoft.AspNet.Diagnostics.Entity.Tests/ApiConsistencyTestBase.cs @@ -0,0 +1,142 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Data.Entity +{ + public abstract class ApiConsistencyTestBase + { + protected const BindingFlags PublicInstance + = BindingFlags.Instance | BindingFlags.Public; + + protected const BindingFlags AnyInstance + = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + + [Fact] + public void Public_inheritable_apis_should_be_virtual() + { + var nonVirtualMethods + = (from type in GetAllTypes(TargetAssembly.GetTypes()) + where type.IsVisible + && !type.IsSealed + && type.GetConstructors(AnyInstance).Any(c => c.IsPublic || c.IsFamily || c.IsFamilyOrAssembly) + && type.Namespace != null + && !type.Namespace.EndsWith(".Compiled") + from method in type.GetMethods(PublicInstance) + where method.DeclaringType == type + && !(method.IsVirtual && !method.IsFinal) + select type.FullName + "." + method.Name) + .ToList(); + + Assert.False( + nonVirtualMethods.Any(), + "\r\n-- Missing virtual APIs --\r\n" + string.Join("\r\n", nonVirtualMethods)); + } + + [Fact] + public void Public_api_arguments_should_have_not_null_annotation() + { + var parametersMissingAttribute + = (from type in GetAllTypes(TargetAssembly.GetTypes()) + where type.IsVisible && !typeof(Delegate).IsAssignableFrom(type) + let interfaceMappings = type.GetInterfaces().Select(type.GetInterfaceMap) + let events = type.GetEvents() + from method in type.GetMethods(PublicInstance | BindingFlags.Static) + .Concat(type.GetConstructors()) + where method.DeclaringType == type + where type.IsInterface || !interfaceMappings.Any(im => im.TargetMethods.Contains(method)) + where !events.Any(e => e.AddMethod == method || e.RemoveMethod == method) + from parameter in method.GetParameters() + where !parameter.ParameterType.IsValueType + && !parameter.GetCustomAttributes() + .Any( + a => a.GetType().Name == "NotNullAttribute" + || a.GetType().Name == "CanBeNullAttribute") + select type.FullName + "." + method.Name + "[" + parameter.Name + "]") + .ToList(); + + Assert.False( + parametersMissingAttribute.Any(), + "\r\n-- Missing NotNull annotations --\r\n" + string.Join("\r\n", parametersMissingAttribute)); + } + + [Fact] + public void Async_methods_should_have_overload_with_cancellation_token_and_end_with_async_suffix() + { + var asyncMethods + = (from type in GetAllTypes(TargetAssembly.GetTypes()) + where type.IsVisible + from method in type.GetMethods(PublicInstance | BindingFlags.Static) + where method.DeclaringType == type + where typeof(Task).IsAssignableFrom(method.ReturnType) + select method).ToList(); + + var asyncMethodsWithToken + = (from method in asyncMethods + where method.GetParameters().Any(pi => pi.ParameterType == typeof(CancellationToken)) + select method).ToList(); + + var asyncMethodsWithoutToken + = (from method in asyncMethods + where method.GetParameters().All(pi => pi.ParameterType != typeof(CancellationToken)) + select method).ToList(); + + var missingOverloads + = (from methodWithoutToken in asyncMethodsWithoutToken + where !asyncMethodsWithToken + .Any(methodWithToken => methodWithoutToken.Name == methodWithToken.Name + && methodWithoutToken.ReflectedType == methodWithToken.ReflectedType) + // ReSharper disable once PossibleNullReferenceException + select methodWithoutToken.DeclaringType.Name + "." + methodWithoutToken.Name) + .Except(GetCancellationTokenExceptions()) + .ToList(); + + Assert.False( + missingOverloads.Any(), + "\r\n-- Missing async overloads --\r\n" + string.Join("\r\n", missingOverloads)); + + var missingSuffixMethods + = asyncMethods + .Where(method => !method.Name.EndsWith("Async")) + .Select(method => method.DeclaringType.Name + "." + method.Name) + .Except(GetAsyncSuffixExceptions()) + .ToList(); + + Assert.False( + missingSuffixMethods.Any(), + "\r\n-- Missing async suffix --\r\n" + string.Join("\r\n", missingSuffixMethods)); + } + + protected virtual IEnumerable GetCancellationTokenExceptions() + { + return Enumerable.Empty(); + } + + protected virtual IEnumerable GetAsyncSuffixExceptions() + { + return Enumerable.Empty(); + } + + protected abstract Assembly TargetAssembly { get; } + + protected virtual IEnumerable GetAllTypes(IEnumerable types) + { + foreach (var type in types) + { + yield return type; + + foreach (var nestedType in GetAllTypes(type.GetNestedTypes())) + { + yield return nestedType; + } + } + } + } +} diff --git a/test/Microsoft.AspNet.Diagnostics.Entity.Tests/Helpers/AssertHelpers.cs b/test/Microsoft.AspNet.Diagnostics.Entity.Tests/Helpers/AssertHelpers.cs index bc230c5419..0a5feae8f0 100644 --- a/test/Microsoft.AspNet.Diagnostics.Entity.Tests/Helpers/AssertHelpers.cs +++ b/test/Microsoft.AspNet.Diagnostics.Entity.Tests/Helpers/AssertHelpers.cs @@ -10,32 +10,32 @@ namespace Microsoft.AspNet.Diagnostics.Entity.Tests.Helpers { public static void DisplaysScaffoldFirstMigration(Type contextType, string content) { - Assert.Contains(Strings.DatabaseErrorPage_NoDbOrMigrationsTitle(contextType.Name), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", contextType.Name), content); } public static void NotDisplaysScaffoldFirstMigration(Type contextType, string content) { - Assert.DoesNotContain(Strings.DatabaseErrorPage_NoDbOrMigrationsTitle(contextType.Name), content); + Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", contextType.Name), content); } public static void DisplaysApplyMigrations(Type contextType, string content) { - Assert.Contains(Strings.DatabaseErrorPage_PendingMigrationsTitle(contextType.Name), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingMigrationsTitle", contextType.Name), content); } public static void NotDisplaysApplyMigrations(Type contextType, string content) { - Assert.DoesNotContain(Strings.DatabaseErrorPage_PendingMigrationsTitle(contextType.Name), content); + Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingMigrationsTitle", contextType.Name), content); } public static void DisplaysScaffoldNextMigraion(Type contextType, string content) { - Assert.Contains(Strings.DatabaseErrorPage_PendingChangesTitle(contextType.Name), content); + Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingChangesTitle", contextType.Name), content); } public static void NotDisplaysScaffoldNextMigraion(Type contextType, string content) { - Assert.DoesNotContain(Strings.DatabaseErrorPage_PendingChangesTitle(contextType.Name), content); + Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingChangesTitle", contextType.Name), content); } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Diagnostics.Entity.Tests/Helpers/StringHelpers.cs b/test/Microsoft.AspNet.Diagnostics.Entity.Tests/Helpers/StringHelpers.cs new file mode 100644 index 0000000000..9838f3b156 --- /dev/null +++ b/test/Microsoft.AspNet.Diagnostics.Entity.Tests/Helpers/StringHelpers.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Linq; +using System.Reflection; + +namespace Microsoft.AspNet.Diagnostics.Entity.Tests.Helpers +{ + public class StringsHelpers + { + public static string GetResourceString(string stringName, params object[] parameters) + { + var strings = typeof(DatabaseErrorPageMiddleware).GetTypeInfo().Assembly.GetType("Microsoft.AspNet.Diagnostics.Entity.Strings").GetTypeInfo(); + var method = strings.GetDeclaredMethods(stringName).Single(); + return (string)method.Invoke(null, parameters); + } + } +} \ No newline at end of file