From 312e0da556e491a1a5b120a3c6d5626f5b5e2edc Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Fri, 18 Aug 2017 09:45:12 -0700 Subject: [PATCH] Fix case sensitivity on Startup classes and methods (#1166) --- .../Internal/StartupLoader.cs | 8 ++--- .../Fakes/StartupCaseInsensitive.cs | 27 ++++++++++++++ .../StartupManagerTests.cs | 35 +++++++++++++++++++ 3 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 test/Microsoft.AspNetCore.Hosting.Tests/Fakes/StartupCaseInsensitive.cs diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/StartupLoader.cs b/src/Microsoft.AspNetCore.Hosting/Internal/StartupLoader.cs index cc65dd300b..e373ed0d64 100644 --- a/src/Microsoft.AspNetCore.Hosting/Internal/StartupLoader.cs +++ b/src/Microsoft.AspNetCore.Hosting/Internal/StartupLoader.cs @@ -94,8 +94,8 @@ namespace Microsoft.AspNetCore.Hosting.Internal // Full scan var definedTypes = assembly.DefinedTypes.ToList(); - var startupType1 = definedTypes.Where(info => info.Name.Equals(startupNameWithEnv, StringComparison.Ordinal)); - var startupType2 = definedTypes.Where(info => info.Name.Equals(startupNameWithoutEnv, StringComparison.Ordinal)); + var startupType1 = definedTypes.Where(info => info.Name.Equals(startupNameWithEnv, StringComparison.OrdinalIgnoreCase)); + var startupType2 = definedTypes.Where(info => info.Name.Equals(startupNameWithoutEnv, StringComparison.OrdinalIgnoreCase)); var typeInfo = startupType1.Concat(startupType2).FirstOrDefault(); if (typeInfo != null) @@ -140,14 +140,14 @@ namespace Microsoft.AspNetCore.Hosting.Internal var methodNameWithNoEnv = string.Format(CultureInfo.InvariantCulture, methodName, ""); var methods = startupType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); - var selectedMethods = methods.Where(method => method.Name.Equals(methodNameWithEnv)).ToList(); + var selectedMethods = methods.Where(method => method.Name.Equals(methodNameWithEnv, StringComparison.OrdinalIgnoreCase)).ToList(); if (selectedMethods.Count > 1) { throw new InvalidOperationException(string.Format("Having multiple overloads of method '{0}' is not supported.", methodNameWithEnv)); } if (selectedMethods.Count == 0) { - selectedMethods = methods.Where(method => method.Name.Equals(methodNameWithNoEnv)).ToList(); + selectedMethods = methods.Where(method => method.Name.Equals(methodNameWithNoEnv, StringComparison.OrdinalIgnoreCase)).ToList(); if (selectedMethods.Count > 1) { throw new InvalidOperationException(string.Format("Having multiple overloads of method '{0}' is not supported.", methodNameWithNoEnv)); diff --git a/test/Microsoft.AspNetCore.Hosting.Tests/Fakes/StartupCaseInsensitive.cs b/test/Microsoft.AspNetCore.Hosting.Tests/Fakes/StartupCaseInsensitive.cs new file mode 100644 index 0000000000..0c85ad5413 --- /dev/null +++ b/test/Microsoft.AspNetCore.Hosting.Tests/Fakes/StartupCaseInsensitive.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting.Fakes; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Hosting.Tests.Fakes +{ + class StartupCaseInsensitive + { + public static IServiceProvider ConfigureCaseInsensitiveServices(IServiceCollection services) + { + services.AddOptions(); + services.Configure(o => + { + o.Configured = true; + o.Environment = "ConfigureCaseInsensitiveServices"; + }); + return services.BuildServiceProvider(); + } + + public void ConfigureCaseInsensitive(IApplicationBuilder app) + { + } + } +} diff --git a/test/Microsoft.AspNetCore.Hosting.Tests/StartupManagerTests.cs b/test/Microsoft.AspNetCore.Hosting.Tests/StartupManagerTests.cs index fc655799c6..81d9d51aae 100644 --- a/test/Microsoft.AspNetCore.Hosting.Tests/StartupManagerTests.cs +++ b/test/Microsoft.AspNetCore.Hosting.Tests/StartupManagerTests.cs @@ -100,6 +100,41 @@ namespace Microsoft.AspNetCore.Hosting.Tests Assert.Equal("A public method named 'ConfigureBoom' or 'Configure' could not be found in the 'Microsoft.AspNetCore.Hosting.Fakes.StartupBoom' type.", ex.Message); } + [Theory] + [InlineData("caseinsensitive")] + [InlineData("CaseInsensitive")] + [InlineData("CASEINSENSITIVE")] + [InlineData("CaSEiNSENsitiVE")] + public void FindsStartupClassCaseInsensitive(string environment) + { + var type = StartupLoader.FindStartupType("Microsoft.AspNetCore.Hosting.Tests", environment); + + Assert.Equal("StartupCaseInsensitive", type.Name); + } + + [Theory] + [InlineData("caseinsensitive")] + [InlineData("CaseInsensitive")] + [InlineData("CASEINSENSITIVE")] + [InlineData("CaSEiNSENsitiVE")] + public void StartupClassAddsConfigureServicesToApplicationServicesCaseInsensitive(string environment) + { + var services = new ServiceCollection() + .AddSingleton, DefaultServiceProviderFactory>() + .BuildServiceProvider(); + var type = StartupLoader.FindStartupType("Microsoft.AspNetCore.Hosting.Tests", environment); + var startup = StartupLoader.LoadMethods(services, type, environment); + + var app = new ApplicationBuilder(services); + app.ApplicationServices = startup.ConfigureServicesDelegate(new ServiceCollection()); + startup.ConfigureDelegate(app); // By this not throwing, it found "ConfigureCaseInsensitive" + + var options = app.ApplicationServices.GetRequiredService>().Value; + Assert.NotNull(options); + Assert.True(options.Configured); + Assert.Equal("ConfigureCaseInsensitiveServices", options.Environment); + } + [Fact] public void StartupWithTwoConfiguresThrows() {