diff --git a/samples/MvcSandbox/Startup.cs b/samples/MvcSandbox/Startup.cs index 0b3360ec8a..d9f96bf08b 100644 --- a/samples/MvcSandbox/Startup.cs +++ b/samples/MvcSandbox/Startup.cs @@ -14,7 +14,7 @@ namespace MvcSandbox // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_2); + services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Latest); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcEndpointDataSource.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcEndpointDataSource.cs index 4150ed26f3..128e699774 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcEndpointDataSource.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcEndpointDataSource.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Patterns; +using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Mvc.Internal @@ -59,10 +60,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal _httpContextInstance = new DefaultHttpContext() { RequestServices = serviceProvider }; ConventionalEndpointInfos = new List(); - - Extensions.Primitives.ChangeToken.OnChange( - GetCompositeChangeToken, - UpdateEndpoints); } private List CreateEndpoints() @@ -454,7 +451,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal return new CompositeChangeToken(changeTokens); } - public override IChangeToken GetChangeToken() => GetCompositeChangeToken(); + public override IChangeToken GetChangeToken() => NullChangeToken.Singleton; public override IReadOnlyList Endpoints { @@ -479,14 +476,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal } } - private void UpdateEndpoints() - { - lock (_lock) - { - _endpoints = CreateEndpoints(); - } - } - public List ConventionalEndpointInfos { get; } private class SuppressLinkGenerationMetadata : ISuppressLinkGenerationMetadata { } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ServiceFilterAttribute.cs b/src/Microsoft.AspNetCore.Mvc.Core/ServiceFilterAttribute.cs index 525d1a82bb..9e16cb4715 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ServiceFilterAttribute.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ServiceFilterAttribute.cs @@ -3,7 +3,6 @@ using System; using System.Diagnostics; -using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.DependencyInjection; @@ -58,14 +57,11 @@ namespace Microsoft.AspNetCore.Mvc throw new ArgumentNullException(nameof(serviceProvider)); } - var service = serviceProvider.GetRequiredService(ServiceType); - - var filter = service as IFilterMetadata; - if (filter == null) + var filter = (IFilterMetadata)serviceProvider.GetRequiredService(ServiceType); + if (filter is IFilterFactory filterFactory) { - throw new InvalidOperationException(Resources.FormatFilterFactoryAttribute_TypeMustImplementIFilter( - typeof(ServiceFilterAttribute).Name, - typeof(IFilterMetadata).Name)); + // Unwrap filter factories + filter = filterFactory.CreateInstance(serviceProvider); } return filter; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/TypeFilterAttribute.cs b/src/Microsoft.AspNetCore.Mvc.Core/TypeFilterAttribute.cs index bc5c19802f..a2048512a6 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/TypeFilterAttribute.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/TypeFilterAttribute.cs @@ -73,11 +73,17 @@ namespace Microsoft.AspNetCore.Mvc if (_factory == null) { var argumentTypes = Arguments?.Select(a => a.GetType())?.ToArray(); - _factory = ActivatorUtilities.CreateFactory(ImplementationType, argumentTypes ?? Type.EmptyTypes); } - return (IFilterMetadata)_factory(serviceProvider, Arguments); + var filter = (IFilterMetadata)_factory(serviceProvider, Arguments); + if (filter is IFilterFactory filterFactory) + { + // Unwrap filter factories + filter = filterFactory.CreateInstance(serviceProvider); + } + + return filter; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Testing/Handlers/RedirectHandler.cs b/src/Microsoft.AspNetCore.Mvc.Testing/Handlers/RedirectHandler.cs index 63158713d3..71198d3d75 100644 --- a/src/Microsoft.AspNetCore.Mvc.Testing/Handlers/RedirectHandler.cs +++ b/src/Microsoft.AspNetCore.Mvc.Testing/Handlers/RedirectHandler.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; @@ -49,13 +50,14 @@ namespace Microsoft.AspNetCore.Mvc.Testing.Handlers protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var remainingRedirects = MaxRedirects; - + var redirectRequest = new HttpRequestMessage(); var originalRequestContent = HasBody(request) ? await DuplicateRequestContent(request) : null; + CopyRequestHeaders(request.Headers, redirectRequest.Headers); var response = await base.SendAsync(request, cancellationToken); while (IsRedirect(response) && remainingRedirects >= 0) { remainingRedirects--; - var redirectRequest = GetRedirectRequest(response, originalRequestContent); + UpdateRedirectRequest(response, redirectRequest, originalRequestContent); originalRequestContent = HasBody(redirectRequest) ? await DuplicateRequestContent(redirectRequest) : null; response = await base.SendAsync(redirectRequest, cancellationToken); } @@ -95,6 +97,16 @@ namespace Microsoft.AspNetCore.Mvc.Testing.Handlers } } + private static void CopyRequestHeaders( + HttpRequestHeaders originalRequestHeaders, + HttpRequestHeaders newRequestHeaders) + { + foreach (var header in originalRequestHeaders) + { + newRequestHeaders.Add(header.Key, header.Value); + } + } + private static async Task<(Stream originalBody, Stream copy)> CopyBody(HttpRequestMessage request) { var originalBody = await request.Content.ReadAsStreamAsync(); @@ -116,8 +128,9 @@ namespace Microsoft.AspNetCore.Mvc.Testing.Handlers return (originalBody, bodyCopy); } - private static HttpRequestMessage GetRedirectRequest( + private static void UpdateRedirectRequest( HttpResponseMessage response, + HttpRequestMessage redirect, HttpContent originalContent) { var location = response.Headers.Location; @@ -128,34 +141,31 @@ namespace Microsoft.AspNetCore.Mvc.Testing.Handlers location); } - var redirect = !ShouldKeepVerb(response) ? - new HttpRequestMessage(HttpMethod.Get, location) : - new HttpRequestMessage(response.RequestMessage.Method, location) - { - Content = originalContent - }; - - foreach (var header in response.RequestMessage.Headers) + redirect.RequestUri = location; + if (!ShouldKeepVerb(response)) { - redirect.Headers.Add(header.Key, header.Value); + redirect.Method = HttpMethod.Get; + } + else + { + redirect.Method = response.RequestMessage.Method; + redirect.Content = originalContent; } foreach (var property in response.RequestMessage.Properties) { redirect.Properties.Add(property.Key, property.Value); } - - return redirect; } private static bool ShouldKeepVerb(HttpResponseMessage response) => response.StatusCode == HttpStatusCode.RedirectKeepVerb || (int)response.StatusCode == 308; - private bool IsRedirect(HttpResponseMessage response) => + private bool IsRedirect(HttpResponseMessage response) => response.StatusCode == HttpStatusCode.MovedPermanently || response.StatusCode == HttpStatusCode.Redirect || response.StatusCode == HttpStatusCode.RedirectKeepVerb || (int)response.StatusCode == 308; } -} +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/MvcEndpointDataSourceTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/MvcEndpointDataSourceTests.cs index 55fd51e0b8..fbee5e6f55 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/MvcEndpointDataSourceTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/MvcEndpointDataSourceTests.cs @@ -133,7 +133,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal Assert.True(actionInvokerCalled); } - [Fact] + [Fact(Skip = "https://github.com/aspnet/Routing/issues/722")] public void GetChangeToken_MultipleChangeTokenProviders_ComposedResult() { // Arrange @@ -287,7 +287,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal actionDescriptorCollectionProviderMock.VerifyGet(m => m.ActionDescriptors, Times.Once); } - [Fact] + [Fact(Skip = "https://github.com/aspnet/Routing/issues/722")] public void Endpoints_ChangeTokenTriggered_EndpointsRecreated() { // Arrange diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ServiceFilterAttributeTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ServiceFilterAttributeTest.cs new file mode 100644 index 0000000000..e21e55018c --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ServiceFilterAttributeTest.cs @@ -0,0 +1,62 @@ +// 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.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.AspNetCore.Mvc +{ + public class ServiceFilterAttributeTest + { + [Fact] + public void CreateService_GetsFilterFromServiceProvider() + { + // Arrange + var expected = new TestFilter(); + var serviceProvider = new ServiceCollection() + .AddSingleton(expected) + .BuildServiceProvider(); + + var serviceFilter = new ServiceFilterAttribute(typeof(TestFilter)); + + // Act + var filter = serviceFilter.CreateInstance(serviceProvider); + + // Assert + Assert.Same(expected, filter); + } + + [Fact] + public void CreateService_UnwrapsFilterFactory() + { + // Arrange + var serviceProvider = new ServiceCollection() + .AddSingleton(new TestFilterFactory()) + .BuildServiceProvider(); + + var serviceFilter = new ServiceFilterAttribute(typeof(TestFilterFactory)); + + // Act + var filter = serviceFilter.CreateInstance(serviceProvider); + + // Assert + Assert.IsType(filter); + } + + public class TestFilter : IFilterMetadata + { + } + + public class TestFilterFactory : IFilterFactory + { + public bool IsReusable => throw new NotImplementedException(); + + public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) + { + return new TestFilter(); + } + } + } +} diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/TypeFilterAttributeTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/TypeFilterAttributeTest.cs new file mode 100644 index 0000000000..27d407b837 --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/TypeFilterAttributeTest.cs @@ -0,0 +1,116 @@ +// 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.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.AspNetCore.Mvc +{ + public class TypeFilterAttributeTest + { + [Fact] + public void CreateService_TypeActivatesImplementationType() + { + // Arrange + var value = "Some value"; + var uri = new Uri("http://www.asp.net"); + var serviceProvider = new ServiceCollection() + .AddSingleton(value) + .AddSingleton(uri) + .BuildServiceProvider(); + + var typeFilter = new TypeFilterAttribute(typeof(TestFilter)); + + // Act + var filter = typeFilter.CreateInstance(serviceProvider); + + // Assert + var testFilter = Assert.IsType(filter); + Assert.Same(value, testFilter.Value); + Assert.Same(uri, testFilter.Uri); + } + + [Fact] + public void CreateService_UsesArguments() + { + // Arrange + var value = "Some value"; + var uri = new Uri("http://www.asp.net"); + var serviceProvider = new ServiceCollection() + .AddSingleton("Value in DI") + .AddSingleton(uri) + .BuildServiceProvider(); + + var typeFilter = new TypeFilterAttribute(typeof(TestFilter)) + { + Arguments = new[] { value, } + }; + + // Act + var filter = typeFilter.CreateInstance(serviceProvider); + + // Assert + var testFilter = Assert.IsType(filter); + Assert.Same(value, testFilter.Value); + Assert.Same(uri, testFilter.Uri); + } + + [Fact] + public void CreateService_UnwrapsFilterFactory() + { + // Arrange + var value = "Some value"; + var uri = new Uri("http://www.asp.net"); + var serviceProvider = new ServiceCollection() + .AddSingleton("Value in DI") + .AddSingleton(uri) + .BuildServiceProvider(); + + var typeFilter = new TypeFilterAttribute(typeof(TestFilterFactory)) + { + Arguments = new[] { value, } + }; + + // Act + var filter = typeFilter.CreateInstance(serviceProvider); + + // Assert + var testFilter = Assert.IsType(filter); + Assert.Same(value, testFilter.Value); + Assert.Same(uri, testFilter.Uri); + } + + public class TestFilter : IFilterMetadata + { + public TestFilter(string value, Uri uri) + { + Value = value; + Uri = uri; + } + + public string Value { get; } + public Uri Uri { get; } + } + + public class TestFilterFactory : IFilterFactory + { + private readonly string _value; + private readonly Uri _uri; + + public TestFilterFactory(string value, Uri uri) + { + _value = value; + _uri = uri; + } + + public bool IsReusable => throw new NotImplementedException(); + + public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) + { + return new TestFilter(_value, _uri); + } + } + } +} diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApiExplorerTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApiExplorerTest.cs index d216ad4aff..40e556ad72 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApiExplorerTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApiExplorerTest.cs @@ -1087,7 +1087,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests }); } - [Fact] + [Fact(Skip = "https://github.com/aspnet/Routing/issues/722")] public async Task ApiExplorer_Updates_WhenActionDescriptorCollectionIsUpdated() { // Act - 1 diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApplicationModelTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApplicationModelTest.cs index a698af7ba4..dcb50e1d8e 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApplicationModelTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ApplicationModelTest.cs @@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal("From Header - HelloWorld", body); } - [Fact] + [Fact(Skip = "https://github.com/aspnet/Routing/issues/721")] public async Task ActionModelSuppressedForPathMatching_CannotBeRouted() { // Arrange & Act diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsEndpointRoutingTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsEndpointRoutingTests.cs index 44402ff200..82867e6ed5 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsEndpointRoutingTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsEndpointRoutingTests.cs @@ -1,34 +1,13 @@ // 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.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Cors.Infrastructure; -using Xunit; - namespace Microsoft.AspNetCore.Mvc.FunctionalTests { - public class CorsEndpointRoutingTests : CorsTestsBase + public class CorsEndpointRoutingTests : CorsTestsBase { - public CorsEndpointRoutingTests(MvcTestFixture fixture) + public CorsEndpointRoutingTests(MvcTestFixture fixture) : base(fixture) { } - - [Fact] // This intentionally returns a 405 with endpoint routing - public override async Task PreflightRequestOnNonCorsEnabledController_DoesNotMatchTheAction() - { - // Arrange - var request = new HttpRequestMessage(new HttpMethod("OPTIONS"), "http://localhost/NonCors/Post"); - request.Headers.Add(CorsConstants.Origin, "http://example.com"); - request.Headers.Add(CorsConstants.AccessControlRequestMethod, "POST"); - - // Act - var response = await Client.SendAsync(request); - - // Assert - Assert.Equal(HttpStatusCode.MethodNotAllowed, response.StatusCode); } - } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsTests.cs index 4d241ddeb0..512fc5ea90 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsTests.cs @@ -1,13 +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.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Cors.Infrastructure; +using Xunit; + namespace Microsoft.AspNetCore.Mvc.FunctionalTests { - public class CorsTests : CorsTestsBase + public class CorsTests : CorsTestsBase { - public CorsTests(MvcTestFixture fixture) + public CorsTests(MvcTestFixture fixture) : base(fixture) { } + + [Fact] + public override async Task PreflightRequestOnNonCorsEnabledController_DoesNotMatchTheAction() + { + // Arrange + var request = new HttpRequestMessage(new HttpMethod("OPTIONS"), "http://localhost/NonCors/Post"); + request.Headers.Add(CorsConstants.Origin, "http://example.com"); + request.Headers.Add(CorsConstants.AccessControlRequestMethod, "POST"); + + // Act + var response = await Client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsTestsBase.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsTestsBase.cs index 899ce4e792..01e9e900eb 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsTestsBase.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/CorsTestsBase.cs @@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests var response = await Client.SendAsync(request); // Assert - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + Assert.Equal(HttpStatusCode.MethodNotAllowed, response.StatusCode); } [Theory] diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/EndpointRoutingTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/EndpointRoutingTest.cs index 81a21798eb..f82be33703 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/EndpointRoutingTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/EndpointRoutingTest.cs @@ -10,9 +10,9 @@ using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests { - public class EndpointRoutingTest : RoutingTestsBase + public class EndpointRoutingTest : RoutingTestsBase { - public EndpointRoutingTest(MvcTestFixture fixture) + public EndpointRoutingTest(MvcTestFixture fixture) : base(fixture) { } @@ -32,26 +32,6 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.True(result); } - [Fact] - public override Task AttributeRoutedAction_InArea_StaysInArea_ActionDoesntExist() - { - // By design, this test cannot work in EndpointRouting world. This is because in case of old routing test - // when a link generation to an attribute routed controller with a non-existing action does not succeeed, - // the next route in the route collection is considered and since the next route in the route collection is - // a conventional area route, the old routing test succeeds. But this cannot happen in case of endpoint - // routing as the action does not exist to begin with. - return Task.CompletedTask; - } - - [Fact] - public override Task ConventionalRoutedAction_InArea_StaysInArea() - { - // By design, this test cannot work in EndpointRouting world. In old routing test a link is being generated - // to a non-existing action on a controller which is in an area. In case of endpoint routing, we cannot - // generate links as the action does not exist to begin with. - return Task.CompletedTask; - } - [Fact] public async override Task RouteData_Routers_ConventionalRoute() { @@ -97,21 +77,6 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal(HttpStatusCode.MethodNotAllowed, response.StatusCode); } - // Endpoint routing exposes HTTP 405s for HTTP method mismatches - [Fact] - public override async Task AttributeRoutedAction_MultipleRouteAttributes_RouteAttributeTemplatesIgnoredForOverrideActions() - { - // Arrange - var url = "http://localhost/api/v1/Maps"; - - // Act - var response = await Client.SendAsync(new HttpRequestMessage(new HttpMethod("POST"), url)); - - // Assert - Assert.Equal(HttpStatusCode.MethodNotAllowed, response.StatusCode); - } - - // Endpoint routing exposes HTTP 405s for HTTP method mismatches [Theory] [MemberData(nameof(AttributeRoutedAction_MultipleRouteAttributes_WithMultipleHttpAttributes_RespectsConstraintsData))] public override async Task AttributeRoutedAction_MultipleRouteAttributes_WithMultipleHttpAttributes_RespectsConstraints( diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs index 23dce2a053..5ac55864af 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/GlobalAuthorizationFilterTest.cs @@ -6,9 +6,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Testing; -using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests @@ -58,11 +56,9 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests public async Task AuthorizationPoliciesDoNotCombine_WithV2_0() { // Arrange & Act - var factory = Factory.WithWebHostBuilder( - builder => builder.ConfigureServices( - services => services.Configure( - options => options.CompatibilityVersion = CompatibilityVersion.Version_2_0))); - var client = factory.CreateDefaultClient(); + var client = Factory + .WithWebHostBuilder(builder => builder.UseStartup()) + .CreateDefaultClient(); var response = await client.PostAsync("http://localhost/Administration/SignInCookie2", null); // Assert diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/HtmlGenerationTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/HtmlGenerationTest.cs index 8c7984814e..65ba3292dd 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/HtmlGenerationTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/HtmlGenerationTest.cs @@ -10,8 +10,8 @@ using System.Net.Http.Headers; using System.Reflection; using System.Text; using System.Threading.Tasks; -using AngleSharp.Dom; -using AngleSharp.Dom.Html; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests @@ -26,14 +26,21 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests MvcTestFixture fixture, MvcEncodedTestFixture encodedFixture) { + Factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder); + Client = fixture.CreateDefaultClient(); EncodedClient = encodedFixture.CreateDefaultClient(); } + private static void ConfigureWebHostBuilder(IWebHostBuilder builder) => + builder.UseStartup(); + public HttpClient Client { get; } public HttpClient EncodedClient { get; } + public WebApplicationFactory Factory { get; } + public static TheoryData WebPagesData { get @@ -131,6 +138,35 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests } } + [Fact] + public async Task HtmlGenerationWebSite_LinkGeneration_With21CompatibilityBehavior() + { + // Arrange + var client = Factory + .WithWebHostBuilder(builder => builder.UseStartup()) + .CreateDefaultClient(); + var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8"); + var outputFile = "compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index21Compat.html"; + var expectedContent = + await ResourceFile.ReadResourceAsync(_resourcesAssembly, outputFile, sourceFile: false); + + // Act + // The host is not important as everything runs in memory and tests are isolated from each other. + var response = await client.GetAsync("http://localhost/HtmlGeneration_Home/"); + var responseContent = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(expectedMediaType, response.Content.Headers.ContentType); + + responseContent = responseContent.Trim(); +#if GENERATE_BASELINES + ResourceFile.UpdateFile(_resourcesAssembly, outputFile, expectedContent, responseContent); +#else + Assert.Equal(expectedContent.Trim(), responseContent, ignoreLineEndingDifferences: true); +#endif + } + public static TheoryData EncodedPagesData { get diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Infrastructure/MvcTestFixture.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Infrastructure/MvcTestFixture.cs index a7d4a643de..cf1ed53098 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Infrastructure/MvcTestFixture.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Infrastructure/MvcTestFixture.cs @@ -3,7 +3,6 @@ using System.Globalization; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; @@ -26,9 +25,6 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests var testSink = new TestSink(); var loggerFactory = new TestLoggerFactory(testSink, enabled: true); services.AddSingleton(loggerFactory); - - services.Configure( - options => options.CompatibilityVersion = CompatibilityVersion.Version_2_1); }); } diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs index 88be27634f..3c90af4882 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs @@ -919,7 +919,7 @@ Hello from /Pages/WithViewStart/Index.cshtml!"; { // Arrange var expected = -@"Microsoft.AspNetCore.Mvc.Routing.UrlHelper +@"Microsoft.AspNetCore.Mvc.Routing.EndpointRoutingUrlHelper Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper`1[AspNetCore.InjectedPageProperties] Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore.InjectedPageProperties]"; diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RoutingTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RoutingTests.cs index a4fbb4ab58..538d06358c 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RoutingTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RoutingTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Net; +using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Routing; @@ -10,9 +11,9 @@ using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests { - public class RoutingTests : RoutingTestsBase + public class RoutingTests : RoutingTestsBase { - public RoutingTests(MvcTestFixture fixture) + public RoutingTests(MvcTestFixture fixture) : base(fixture) { } @@ -32,6 +33,62 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.False(result); } + // Legacy routing supports linking to actions that don't exist + [Fact] + public async Task AttributeRoutedAction_InArea_StaysInArea_ActionDoesntExist() + { + // Arrange + var url = LinkFrom("http://localhost/ContosoCorp/Trains") + .To(new { action = "Contact", controller = "Home", }); + + // Act + var response = await Client.GetAsync(url); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var body = await response.Content.ReadAsStringAsync(); + var result = JsonConvert.DeserializeObject(body); + + Assert.Equal("Rail", result.Controller); + Assert.Equal("Index", result.Action); + + Assert.Equal("/Travel/Home/Contact", result.Link); + } + + [Fact] + public async Task ConventionalRoutedAction_InArea_StaysInArea() + { + // Arrange + var url = LinkFrom("http://localhost/Travel/Flight").To(new { action = "Contact", controller = "Home", }); + + // Act + var response = await Client.GetAsync(url); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var body = await response.Content.ReadAsStringAsync(); + var result = JsonConvert.DeserializeObject(body); + + Assert.Equal("Flight", result.Controller); + Assert.Equal("Index", result.Action); + + Assert.Equal("/Travel/Home/Contact", result.Link); + } + + // Legacy routing returns 404 when an action does not support a HTTP method. + [Fact] + public override async Task AttributeRoutedAction_MultipleRouteAttributes_RouteAttributeTemplatesIgnoredForOverrideActions() + { + // Arrange + var url = "http://localhost/api/v1/Maps"; + + // Act + var response = await Client.SendAsync(new HttpRequestMessage(new HttpMethod("POST"), url)); + + // Assert + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + } + [Fact] public async override Task RouteData_Routers_ConventionalRoute() { diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RoutingTestsBase.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RoutingTestsBase.cs index 4767f77696..6430ff2005 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RoutingTestsBase.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RoutingTestsBase.cs @@ -340,7 +340,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests var response = await Client.SendAsync(new HttpRequestMessage(new HttpMethod("POST"), url)); // Assert - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + Assert.Equal(HttpStatusCode.MethodNotAllowed, response.StatusCode); } [Theory] @@ -1016,26 +1016,6 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal("/", result.Link); } - [Fact] - public virtual async Task ConventionalRoutedAction_InArea_StaysInArea() - { - // Arrange - var url = LinkFrom("http://localhost/Travel/Flight").To(new { action = "Contact", controller = "Home", }); - - // Act - var response = await Client.GetAsync(url); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("Flight", result.Controller); - Assert.Equal("Index", result.Action); - - Assert.Equal("/Travel/Home/Contact", result.Link); - } - [Fact] public virtual async Task AttributeRoutedAction_LinkToArea() { @@ -1098,26 +1078,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal("/", result.Link); } - [Fact] - public virtual async Task AttributeRoutedAction_InArea_StaysInArea_ActionDoesntExist() - { - // Arrange - var url = LinkFrom("http://localhost/ContosoCorp/Trains") - .To(new { action = "Contact", controller = "Home", }); - - // Act - var response = await Client.GetAsync(url); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var body = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(body); - - Assert.Equal("Rail", result.Controller); - Assert.Equal("Index", result.Action); - - Assert.Equal("/Travel/Home/Contact", result.Link); - } + [Fact] public virtual async Task AttributeRoutedAction_InArea_LinkToConventionalRoutedActionInArea() @@ -1280,13 +1241,13 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal(actionName, result.Action); } - private static LinkBuilder LinkFrom(string url) + protected static LinkBuilder LinkFrom(string url) { return new LinkBuilder(url); } // See TestResponseGenerator in RoutingWebSite for the code that generates this data. - private class RoutingResult + protected class RoutingResult { public string[] ExpectedUrls { get; set; } @@ -1303,7 +1264,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests public string Link { get; set; } } - private class LinkBuilder + protected class LinkBuilder { public LinkBuilder(string url) { diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureTests.cs index 9e5be478f6..afa57b5092 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/TestingInfrastructureTests.cs @@ -2,11 +2,13 @@ using System.Net; using System.Net.Http; using System.Net.Http.Formatting; +using System.Threading; using System.Threading.Tasks; using BasicWebSite; using BasicWebSite.Controllers; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.Mvc.Testing.Handlers; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Xunit; @@ -17,13 +19,14 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests { public TestingInfrastructureTests(WebApplicationFactory fixture) { - var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder); - Client = factory.CreateClient(); + Factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder); + Client = Factory.CreateClient(); } private static void ConfigureWebHostBuilder(IWebHostBuilder builder) => builder.ConfigureTestServices(s => s.AddSingleton()); + public WebApplicationFactory Factory { get; } public HttpClient Client { get; } [Fact] @@ -57,6 +60,22 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Assert.Equal(5, handlerResponse.Body); } + [Fact] + public async Task TestingInfrastructure_RedirectHandlerUsesOriginalRequestHeaders() + { + // Act + var request = new HttpRequestMessage(HttpMethod.Get, "Testing/RedirectHandler/Headers"); + var client = Factory.CreateDefaultClient( + new RedirectHandler(), new TestHandler()); + var response = await client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var modifiedHeaderWasSent = await response.Content.ReadAsStringAsync(); + + Assert.Equal("false", modifiedHeaderWasSent); + } + [Fact] public async Task TestingInfrastructure_PostRedirectGetWorksWithCookies() { @@ -93,5 +112,29 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests Message = "Test"; } } + + private class TestHandler : DelegatingHandler + { + public TestHandler() + { + } + + public TestHandler(HttpMessageHandler innerHandler) : base(innerHandler) + { + } + + public bool HeaderAdded { get; set; } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + if (!HeaderAdded) + { + request.Headers.Add("X-Added-Header", "true"); + HeaderAdded = true; + } + + return base.SendAsync(request, cancellationToken); + } + } } } diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/VersioningEndpointRoutingTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/VersioningEndpointRoutingTests.cs index 2aeb0d2490..30f2ea33ba 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/VersioningEndpointRoutingTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/VersioningEndpointRoutingTests.cs @@ -9,9 +9,9 @@ using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests { - public class VersioningEndpointRoutingTests : VersioningTestsBase + public class VersioningEndpointRoutingTests : VersioningTestsBase { - public VersioningEndpointRoutingTests(MvcTestFixture fixture) + public VersioningEndpointRoutingTests(MvcTestFixture fixture) : base(fixture) { } diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/VersioningTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/VersioningTests.cs index 40e14bdc57..80e057bbd1 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/VersioningTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/VersioningTests.cs @@ -8,9 +8,9 @@ using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests { - public class VersioningTests : VersioningTestsBase + public class VersioningTests : VersioningTestsBase { - public VersioningTests(MvcTestFixture fixture) + public VersioningTests(MvcTestFixture fixture) : base(fixture) { } diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index.Encoded.html b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index.Encoded.html index dfed464b45..c518a8fea6 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index.Encoded.html +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index.Encoded.html @@ -13,7 +13,7 @@ Default Controller
Product Submit Fragment @@ -39,32 +39,32 @@
Non-existent Area diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index.html b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index.html index e80ec4969e..1800bea8a1 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index.html +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index.html @@ -13,7 +13,7 @@ Default Controller
Product Submit Fragment @@ -39,32 +39,32 @@
Non-existent Area diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index21Compat.html b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index21Compat.html new file mode 100644 index 0000000000..59380d72d6 --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/HtmlGenerationWebSite.HtmlGeneration_Home.Index21Compat.html @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.About.html b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.About.html index e675616a89..72ba50bb99 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.About.html +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.About.html @@ -12,8 +12,8 @@

ASP.NET vNext - About

| My Home - | My About - | My Help |

+ | My About + | My Help |

diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Help.html b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Help.html index 0a20fbb435..a3d85388ba 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Help.html +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Help.html @@ -12,8 +12,8 @@

ASP.NET vNext - Help

| My Home - | My About - | My Help |

+ | My About + | My Help |

diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Index.html b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Index.html index 27bc4cf95a..d10ba0b6f4 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Index.html +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Index.html @@ -19,8 +19,8 @@

ASP.NET vNext - Home Page

| My Home - | My About - | My Help |

+ | My About + | My Help |

diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.ViewComponentTagHelpers.html b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.ViewComponentTagHelpers.html index b6caedd04c..c9bec6c144 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.ViewComponentTagHelpers.html +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.ViewComponentTagHelpers.html @@ -12,8 +12,8 @@

ASP.NET vNext -

| My Home - | My About - | My Help |

+ | My About + | My Help |

Items:
diff --git a/test/WebSites/ApiExplorerWebSite/ActionDescriptorChangeProvider.cs b/test/WebSites/ApiExplorerWebSite/ActionDescriptorChangeProvider.cs index abc1b3b8b3..266f99d3aa 100644 --- a/test/WebSites/ApiExplorerWebSite/ActionDescriptorChangeProvider.cs +++ b/test/WebSites/ApiExplorerWebSite/ActionDescriptorChangeProvider.cs @@ -9,20 +9,22 @@ namespace ApiExplorerWebSite { public class ActionDescriptorChangeProvider : IActionDescriptorChangeProvider { - private ActionDescriptorChangeProvider() + public ActionDescriptorChangeProvider(WellKnownChangeToken changeToken) { + ChangeToken = changeToken; } - public static ActionDescriptorChangeProvider Instance { get; } = new ActionDescriptorChangeProvider(); - - public CancellationTokenSource TokenSource { get; private set; } - - public bool HasChanged { get; set; } + public WellKnownChangeToken ChangeToken { get; } public IChangeToken GetChangeToken() { - TokenSource = new CancellationTokenSource(); - return new CancellationChangeToken(TokenSource.Token); + if (ChangeToken.TokenSource.IsCancellationRequested) + { + var changeTokenSource = new CancellationTokenSource(); + return new CancellationChangeToken(changeTokenSource.Token); + } + + return new CancellationChangeToken(ChangeToken.TokenSource.Token); } } } diff --git a/test/WebSites/ApiExplorerWebSite/ApiExplorerRouteChangeConvention.cs b/test/WebSites/ApiExplorerWebSite/ApiExplorerRouteChangeConvention.cs new file mode 100644 index 0000000000..c329b28c42 --- /dev/null +++ b/test/WebSites/ApiExplorerWebSite/ApiExplorerRouteChangeConvention.cs @@ -0,0 +1,35 @@ +// 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 Microsoft.AspNetCore.Mvc.ApplicationModels; + +namespace ApiExplorerWebSite +{ + public class ApiExplorerRouteChangeConvention : Attribute, IActionModelConvention + { + public ApiExplorerRouteChangeConvention(WellKnownChangeToken changeToken) + { + ChangeToken = changeToken; + } + + public WellKnownChangeToken ChangeToken { get; } + + public void Apply(ActionModel action) + { + if (action.Attributes.OfType().Any() && ChangeToken.TokenSource.IsCancellationRequested) + { + action.ActionName = "NewIndex"; + action.Selectors.Clear(); + action.Selectors.Add(new SelectorModel + { + AttributeRouteModel = new AttributeRouteModel + { + Template = "NewIndex" + } + }); + } + } + } +} diff --git a/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerReloadableController.cs b/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerReloadableController.cs index 31103ba0f2..d6372a8a86 100644 --- a/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerReloadableController.cs +++ b/test/WebSites/ApiExplorerWebSite/Controllers/ApiExplorerReloadableController.cs @@ -1,45 +1,23 @@ // 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.Mvc; -using Microsoft.AspNetCore.Mvc.ApplicationModels; namespace ApiExplorerWebSite { [Route("ApiExplorerReload")] public class ApiExplorerReloadableController : Controller { - [ApiExplorerRouteChangeConvention] [Route("Index")] + [Reload] public string Index() => "Hello world"; [Route("Reload")] [PassThru] - public IActionResult Reload() + public IActionResult Reload([FromServices] WellKnownChangeToken changeToken) { - ActionDescriptorChangeProvider.Instance.HasChanged = true; - ActionDescriptorChangeProvider.Instance.TokenSource.Cancel(); + changeToken.TokenSource.Cancel(); return Ok(); } - - public class ApiExplorerRouteChangeConventionAttribute : Attribute, IActionModelConvention - { - public void Apply(ActionModel action) - { - if (ActionDescriptorChangeProvider.Instance.HasChanged) - { - action.ActionName = "NewIndex"; - action.Selectors.Clear(); - action.Selectors.Add(new SelectorModel - { - AttributeRouteModel = new AttributeRouteModel - { - Template = "NewIndex" - } - }); - } - } - } } } diff --git a/test/WebSites/ApiExplorerWebSite/ReloadAttribute.cs b/test/WebSites/ApiExplorerWebSite/ReloadAttribute.cs new file mode 100644 index 0000000000..9cb7222539 --- /dev/null +++ b/test/WebSites/ApiExplorerWebSite/ReloadAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace ApiExplorerWebSite +{ + public class ReloadAttribute : Attribute + { + } +} diff --git a/test/WebSites/ApiExplorerWebSite/Startup.cs b/test/WebSites/ApiExplorerWebSite/Startup.cs index e794f807ef..f5f96abfd5 100644 --- a/test/WebSites/ApiExplorerWebSite/Startup.cs +++ b/test/WebSites/ApiExplorerWebSite/Startup.cs @@ -6,6 +6,7 @@ using System.Linq; using ApiExplorerWebSite.Controllers; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.DependencyInjection; @@ -19,6 +20,8 @@ namespace ApiExplorerWebSite public void ConfigureServices(IServiceCollection services) { services.AddTransient(); + + var wellKnownChangeToken = new WellKnownChangeToken(); services.AddMvc(options => { options.Filters.AddService(typeof(ApiExplorerDataFilter)); @@ -28,17 +31,19 @@ namespace ApiExplorerWebSite typeof(ApiExplorerVisbilityDisabledByConventionController))); options.Conventions.Add(new ApiExplorerInboundOutboundConvention( typeof(ApiExplorerInboundOutBoundController))); + options.Conventions.Add(new ApiExplorerRouteChangeConvention(wellKnownChangeToken)); var jsonOutputFormatter = options.OutputFormatters.OfType().First(); options.OutputFormatters.Clear(); options.OutputFormatters.Add(jsonOutputFormatter); options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter()); - }); + }) + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.AddSingleton(); - services.AddSingleton(ActionDescriptorChangeProvider.Instance); - services.AddSingleton(ActionDescriptorChangeProvider.Instance); + services.AddSingleton(); + services.AddSingleton(wellKnownChangeToken); } public void Configure(IApplicationBuilder app) diff --git a/test/WebSites/ApiExplorerWebSite/WellKnownChangeToken.cs b/test/WebSites/ApiExplorerWebSite/WellKnownChangeToken.cs new file mode 100644 index 0000000000..a862f4f88f --- /dev/null +++ b/test/WebSites/ApiExplorerWebSite/WellKnownChangeToken.cs @@ -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. + +using System.Threading; + +namespace ApiExplorerWebSite +{ + public class WellKnownChangeToken + { + public CancellationTokenSource TokenSource { get; } = new CancellationTokenSource(); + } +} diff --git a/test/WebSites/ApplicationModelWebSite/Startup.cs b/test/WebSites/ApplicationModelWebSite/Startup.cs index 37e97287fb..899b3c13fa 100644 --- a/test/WebSites/ApplicationModelWebSite/Startup.cs +++ b/test/WebSites/ApplicationModelWebSite/Startup.cs @@ -4,6 +4,7 @@ using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace ApplicationModelWebSite @@ -20,7 +21,8 @@ namespace ApplicationModelWebSite options.Conventions.Add(new FromHeaderConvention()); options.Conventions.Add(new MultipleAreasControllerConvention()); options.Conventions.Add(new CloneActionConvention()); - }); + }) + .SetCompatibilityVersion(CompatibilityVersion.Latest); } public void Configure(IApplicationBuilder app) diff --git a/test/WebSites/BasicWebSite/Controllers/TestingController.cs b/test/WebSites/BasicWebSite/Controllers/TestingController.cs index 07e76a3d6b..882ed935c9 100644 --- a/test/WebSites/BasicWebSite/Controllers/TestingController.cs +++ b/test/WebSites/BasicWebSite/Controllers/TestingController.cs @@ -37,6 +37,32 @@ namespace BasicWebSite.Controllers return Ok(new RedirectHandlerResponse { Url = value, Body = number.Value }); } + [HttpGet("Testing/RedirectHandler/Headers")] + public IActionResult RedirectHandlerHeaders() + { + if (!Request.Headers.TryGetValue("X-Added-Header", out var value)) + { + return Content("No header present"); + } + else + { + return RedirectToAction(nameof(RedirectHandlerHeadersRedirect)); + } + } + + [HttpGet("Testing/RedirectHandler/Headers/Redirect")] + public IActionResult RedirectHandlerHeadersRedirect() + { + if (Request.Headers.TryGetValue("X-Added-Header", out var value)) + { + return Content("true"); + } + else + { + return Content("false"); + } + } + [HttpGet("Testing/AntiforgerySimulator/{value}")] public IActionResult AntiforgerySimulator([FromRoute]int value) { diff --git a/test/WebSites/BasicWebSite/StartupRequestLimitSize.cs b/test/WebSites/BasicWebSite/StartupRequestLimitSize.cs index 0338d0b217..066fc406da 100644 --- a/test/WebSites/BasicWebSite/StartupRequestLimitSize.cs +++ b/test/WebSites/BasicWebSite/StartupRequestLimitSize.cs @@ -5,6 +5,7 @@ using System; using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace BasicWebSite @@ -13,7 +14,8 @@ namespace BasicWebSite { public void ConfigureServices(IServiceCollection services) { - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.ConfigureBaseWebSiteAuthPolicies(); } diff --git a/test/WebSites/BasicWebSite/StartupWithCookieTempDataProviderAndCookieConsent.cs b/test/WebSites/BasicWebSite/StartupWithCookieTempDataProviderAndCookieConsent.cs index 0fdb7383b6..db15febae3 100644 --- a/test/WebSites/BasicWebSite/StartupWithCookieTempDataProviderAndCookieConsent.cs +++ b/test/WebSites/BasicWebSite/StartupWithCookieTempDataProviderAndCookieConsent.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace BasicWebSite @@ -10,7 +11,8 @@ namespace BasicWebSite { public void ConfigureServices(IServiceCollection services) { - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.Configure(o => { diff --git a/test/WebSites/BasicWebSite/StartupWithSessionTempDataProvider.cs b/test/WebSites/BasicWebSite/StartupWithSessionTempDataProvider.cs index c05e83cb95..1d868bc638 100644 --- a/test/WebSites/BasicWebSite/StartupWithSessionTempDataProvider.cs +++ b/test/WebSites/BasicWebSite/StartupWithSessionTempDataProvider.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace BasicWebSite @@ -13,7 +14,8 @@ namespace BasicWebSite // CookieTempDataProvider is the default ITempDataProvider, so we must override it with session. services .AddMvc() - .AddSessionStateTempDataProvider(); + .AddSessionStateTempDataProvider() + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.AddSession(); services.ConfigureBaseWebSiteAuthPolicies(); diff --git a/test/WebSites/ControllersFromServicesWebSite/Startup.cs b/test/WebSites/ControllersFromServicesWebSite/Startup.cs index 05653ebde6..b11534fedb 100644 --- a/test/WebSites/ControllersFromServicesWebSite/Startup.cs +++ b/test/WebSites/ControllersFromServicesWebSite/Startup.cs @@ -11,7 +11,7 @@ using ControllersFromServicesWebSite.Components; using ControllersFromServicesWebSite.TagHelpers; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.Extensions.DependencyInjection; @@ -36,7 +36,8 @@ namespace ControllersFromServicesWebSite }) .AddControllersAsServices() .AddViewComponentsAsServices() - .AddTagHelpersAsServices(); + .AddTagHelpersAsServices() + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.AddTransient(); services.AddTransient(); diff --git a/test/WebSites/CorsWebSite/Startup.cs b/test/WebSites/CorsWebSite/Startup.cs index 5c8e115755..6ef084b83b 100644 --- a/test/WebSites/CorsWebSite/Startup.cs +++ b/test/WebSites/CorsWebSite/Startup.cs @@ -1,10 +1,9 @@ // 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.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Cors.Infrastructure; -using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace CorsWebSite @@ -13,7 +12,8 @@ namespace CorsWebSite { public void ConfigureServices(IServiceCollection services) { - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.Configure(options => { options.AddPolicy( diff --git a/test/WebSites/CorsWebSite/StartupWithEndpointRouting.cs b/test/WebSites/CorsWebSite/StartupWith21Compat.cs similarity index 93% rename from test/WebSites/CorsWebSite/StartupWithEndpointRouting.cs rename to test/WebSites/CorsWebSite/StartupWith21Compat.cs index c620d62a58..b34b71f80c 100644 --- a/test/WebSites/CorsWebSite/StartupWithEndpointRouting.cs +++ b/test/WebSites/CorsWebSite/StartupWith21Compat.cs @@ -1,19 +1,19 @@ // 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.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Cors.Infrastructure; -using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace CorsWebSite { - public class StartupWithEndpointRouting + public class StartupWith21Compat { public void ConfigureServices(IServiceCollection services) { - services.AddMvc(options => options.EnableEndpointRouting = true); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.Configure(options => { options.AddPolicy( diff --git a/test/WebSites/ErrorPageMiddlewareWebSite/Startup.cs b/test/WebSites/ErrorPageMiddlewareWebSite/Startup.cs index 864fce79ea..3fc459a06f 100644 --- a/test/WebSites/ErrorPageMiddlewareWebSite/Startup.cs +++ b/test/WebSites/ErrorPageMiddlewareWebSite/Startup.cs @@ -4,6 +4,7 @@ using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace ErrorPageMiddlewareWebSite @@ -13,7 +14,8 @@ namespace ErrorPageMiddlewareWebSite // Set up application services public void ConfigureServices(IServiceCollection services) { - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); } public void Configure(IApplicationBuilder app) diff --git a/test/WebSites/FilesWebSite/Startup.cs b/test/WebSites/FilesWebSite/Startup.cs index aaa363af54..3e1404b3ff 100644 --- a/test/WebSites/FilesWebSite/Startup.cs +++ b/test/WebSites/FilesWebSite/Startup.cs @@ -4,6 +4,7 @@ using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace FilesWebSite @@ -13,7 +14,8 @@ namespace FilesWebSite // Set up application services public void ConfigureServices(IServiceCollection services) { - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); } public void Configure(IApplicationBuilder app) diff --git a/test/WebSites/HtmlGenerationWebSite/Startup.cs b/test/WebSites/HtmlGenerationWebSite/Startup.cs index a0c93159d6..a1b2a64b26 100644 --- a/test/WebSites/HtmlGenerationWebSite/Startup.cs +++ b/test/WebSites/HtmlGenerationWebSite/Startup.cs @@ -4,6 +4,7 @@ using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.TagHelpers; using Microsoft.Extensions.DependencyInjection; @@ -16,7 +17,9 @@ namespace HtmlGenerationWebSite { // Add MVC services to the services container. Change default FormTagHelper.AntiForgery to false. Usually // null which is interpreted as true unless element includes an action attribute. - services.AddMvc().InitializeTagHelper((helper, _) => helper.Antiforgery = false); + services.AddMvc() + .InitializeTagHelper((helper, _) => helper.Antiforgery = false) + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.AddSingleton(typeof(ISignalTokenProviderService<>), typeof(SignalTokenProviderService<>)); services.AddSingleton(); diff --git a/test/WebSites/HtmlGenerationWebSite/StartupWith21CompatibilityBehavior.cs b/test/WebSites/HtmlGenerationWebSite/StartupWith21CompatibilityBehavior.cs new file mode 100644 index 0000000000..5c4fce1ed8 --- /dev/null +++ b/test/WebSites/HtmlGenerationWebSite/StartupWith21CompatibilityBehavior.cs @@ -0,0 +1,55 @@ +// 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.IO; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.TagHelpers; +using Microsoft.Extensions.DependencyInjection; + +namespace HtmlGenerationWebSite +{ + public class StartupWith21CompatibilityBehavior + { + // Set up application services + public void ConfigureServices(IServiceCollection services) + { + // Add MVC services to the services container. Change default FormTagHelper.AntiForgery to false. Usually + // null which is interpreted as true unless element includes an action attribute. + services.AddMvc() + .InitializeTagHelper((helper, _) => helper.Antiforgery = false) + .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); + + services.AddSingleton(typeof(ISignalTokenProviderService<>), typeof(SignalTokenProviderService<>)); + services.AddSingleton(); + } + + public void Configure(IApplicationBuilder app) + { + app.UseStaticFiles(); + app.UseMvc(routes => + { + routes.MapRoute( + name: "areaRoute", + template: "{area:exists}/{controller}/{action}/{id?}", + defaults: new { action = "Index" }); + routes.MapRoute( + name: "productRoute", + template: "Product/{action}", + defaults: new { controller = "Product" }); + routes.MapRoute( + name: "default", + template: "{controller}/{action}/{id?}", + defaults: new { controller = "HtmlGeneration_Home", action = "Index" }); + }); + } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + new WebHostBuilder() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseStartup() + .UseKestrel() + .UseIISIntegration(); + } +} diff --git a/test/WebSites/HtmlGenerationWebSite/StartupWithCultureReplace.cs b/test/WebSites/HtmlGenerationWebSite/StartupWithCultureReplace.cs index ea197babb3..1214b96f88 100644 --- a/test/WebSites/HtmlGenerationWebSite/StartupWithCultureReplace.cs +++ b/test/WebSites/HtmlGenerationWebSite/StartupWithCultureReplace.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Localization; using Microsoft.Extensions.DependencyInjection; namespace HtmlGenerationWebSite diff --git a/test/WebSites/HtmlGenerationWebSite/Views/HtmlGeneration_Home/Index.cshtml b/test/WebSites/HtmlGenerationWebSite/Views/HtmlGeneration_Home/Index.cshtml index c505df763e..24830788f5 100644 --- a/test/WebSites/HtmlGenerationWebSite/Views/HtmlGeneration_Home/Index.cshtml +++ b/test/WebSites/HtmlGenerationWebSite/Views/HtmlGeneration_Home/Index.cshtml @@ -19,7 +19,7 @@ Default Controller
Product Submit Fragment @@ -46,7 +46,7 @@
diff --git a/test/WebSites/RazorBuildWebSite/Startup.cs b/test/WebSites/RazorBuildWebSite/Startup.cs index b66bede92b..3d4858bd55 100644 --- a/test/WebSites/RazorBuildWebSite/Startup.cs +++ b/test/WebSites/RazorBuildWebSite/Startup.cs @@ -4,6 +4,7 @@ using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace RazorBuildWebSite @@ -12,7 +13,8 @@ namespace RazorBuildWebSite { public void ConfigureServices(IServiceCollection services) { - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); } public void Configure(IApplicationBuilder app) diff --git a/test/WebSites/RazorPagesWebSite/Startup.cs b/test/WebSites/RazorPagesWebSite/Startup.cs index fe3cecc4e9..ea3a6bd601 100644 --- a/test/WebSites/RazorPagesWebSite/Startup.cs +++ b/test/WebSites/RazorPagesWebSite/Startup.cs @@ -4,6 +4,7 @@ using System.Globalization; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using RazorPagesWebSite.Conventions; @@ -25,7 +26,8 @@ namespace RazorPagesWebSite options.Conventions.AddPageRoute("/Pages/NotTheRoot", string.Empty); options.Conventions.Add(new CustomModelTypeConvention()); }) - .WithRazorPagesAtContentRoot(); + .WithRazorPagesAtContentRoot() + .SetCompatibilityVersion(CompatibilityVersion.Latest); } public void Configure(IApplicationBuilder app) diff --git a/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs b/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs index 4ee45cae12..0ded866ccf 100644 --- a/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs +++ b/test/WebSites/RazorPagesWebSite/StartupWithBasePath.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using RazorPagesWebSite.Conventions; @@ -24,7 +25,8 @@ namespace RazorPagesWebSite options.Conventions.AuthorizeAreaFolder("Accounts", "/RequiresAuth"); options.Conventions.AllowAnonymousToAreaPage("Accounts", "/RequiresAuth/AllowAnonymous"); options.Conventions.Add(new CustomModelTypeConvention()); - }); + }) + .SetCompatibilityVersion(CompatibilityVersion.Latest); } public void Configure(IApplicationBuilder app) diff --git a/test/WebSites/RazorWebSite/Controllers/EmbeddedViewsController.cs b/test/WebSites/RazorWebSite/Controllers/EmbeddedViewsController.cs index ca653f83a0..d170e5cf57 100644 --- a/test/WebSites/RazorWebSite/Controllers/EmbeddedViewsController.cs +++ b/test/WebSites/RazorWebSite/Controllers/EmbeddedViewsController.cs @@ -7,6 +7,8 @@ namespace RazorWebSite.Controllers { public class EmbeddedViewsController : Controller { + public IActionResult Index() => null; + public IActionResult LookupByName() => View("Index"); public IActionResult LookupByPath() => View("/Views/EmbeddedViews/Index.cshtml"); diff --git a/test/WebSites/RazorWebSite/Startup.cs b/test/WebSites/RazorWebSite/Startup.cs index d0a4244558..c4b02e356f 100644 --- a/test/WebSites/RazorWebSite/Startup.cs +++ b/test/WebSites/RazorWebSite/Startup.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Localization; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.DependencyInjection; @@ -41,7 +42,8 @@ namespace RazorWebSite options.HtmlHelperOptions.ValidationMessageElement = "validationMessageElement"; options.HtmlHelperOptions.ValidationSummaryMessageElement = "validationSummaryElement"; }) - .AddMvcLocalization(LanguageViewLocationExpanderFormat.SubFolder); + .AddMvcLocalization(LanguageViewLocationExpanderFormat.SubFolder) + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.AddTransient(); services.AddTransient(); diff --git a/test/WebSites/RazorWebSite/StartupDataAnnotations.cs b/test/WebSites/RazorWebSite/StartupDataAnnotations.cs index 7ec35e86fa..d3159ea501 100644 --- a/test/WebSites/RazorWebSite/StartupDataAnnotations.cs +++ b/test/WebSites/RazorWebSite/StartupDataAnnotations.cs @@ -6,7 +6,6 @@ using System.Globalization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace RazorWebSite @@ -25,8 +24,8 @@ namespace RazorWebSite { options.DataAnnotationLocalizerProvider = (modelType, stringLocalizerFactory) => stringLocalizerFactory.Create(typeof(SingleType)); - }); - services.Configure(options => options.CompatibilityVersion = CompatibilityVersion.Latest); + }) + .SetCompatibilityVersion(CompatibilityVersion.Latest); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/test/WebSites/RoutingWebSite/Startup.cs b/test/WebSites/RoutingWebSite/Startup.cs index c7b905bffb..984e4cc5c2 100644 --- a/test/WebSites/RoutingWebSite/Startup.cs +++ b/test/WebSites/RoutingWebSite/Startup.cs @@ -1,9 +1,8 @@ // 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.IO; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.DependencyInjection; @@ -14,7 +13,8 @@ namespace RoutingWebSite // Set up application services public void ConfigureServices(IServiceCollection services) { - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.AddScoped(); services.AddSingleton(); @@ -29,8 +29,7 @@ namespace RoutingWebSite "adminRoute", "{area:exists}/{controller}/{action}", new { controller = "Home", action = "Index" }, - new { area = "Travel" } - ); + new { area = "Travel" }); routes.MapRoute( "ActionAsMethod", @@ -43,5 +42,4 @@ namespace RoutingWebSite }); } } -} - +} \ No newline at end of file diff --git a/test/WebSites/RoutingWebSite/StartupWithEndpointRouting.cs b/test/WebSites/RoutingWebSite/StartupWith21Compat.cs similarity index 90% rename from test/WebSites/RoutingWebSite/StartupWithEndpointRouting.cs rename to test/WebSites/RoutingWebSite/StartupWith21Compat.cs index 16bc62d81f..33c10a0275 100644 --- a/test/WebSites/RoutingWebSite/StartupWithEndpointRouting.cs +++ b/test/WebSites/RoutingWebSite/StartupWith21Compat.cs @@ -2,18 +2,19 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace RoutingWebSite { - public class StartupWithEndpointRouting + public class StartupWith21Compat { // Set up application services public void ConfigureServices(IServiceCollection services) { services.AddMvc() - .AddMvcOptions(options => options.EnableEndpointRouting = true); + .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddScoped(); services.AddSingleton(); diff --git a/test/WebSites/SecurityWebSite/Startup.cs b/test/WebSites/SecurityWebSite/Startup.cs index 7dc96a5c2a..08db0bdd8d 100644 --- a/test/WebSites/SecurityWebSite/Startup.cs +++ b/test/WebSites/SecurityWebSite/Startup.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization.Policy; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace SecurityWebSite @@ -14,7 +15,8 @@ namespace SecurityWebSite public void ConfigureServices(IServiceCollection services) { // Add framework services. - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.AddAntiforgery(); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => { diff --git a/test/WebSites/SecurityWebSite/StartupWith20CompatAndGlobalDenyAnonymousFilter.cs b/test/WebSites/SecurityWebSite/StartupWith20CompatAndGlobalDenyAnonymousFilter.cs new file mode 100644 index 0000000000..b674e76fe0 --- /dev/null +++ b/test/WebSites/SecurityWebSite/StartupWith20CompatAndGlobalDenyAnonymousFilter.cs @@ -0,0 +1,41 @@ +// 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 Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authorization.Policy; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Authorization; +using Microsoft.Extensions.DependencyInjection; + +namespace SecurityWebSite +{ + public class StartupWith20CompatAndGlobalDenyAnonymousFilter + { + public void ConfigureServices(IServiceCollection services) + { + services + .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie(options => + { + options.LoginPath = "/Home/Login"; + options.LogoutPath = "/Home/Logout"; + }).AddCookie("Cookie2"); + + services.AddMvc(o => + { + o.Filters.Add(new AuthorizeFilter()); + }) + .SetCompatibilityVersion(CompatibilityVersion.Version_2_0); + + services.AddScoped(); + } + + public void Configure(IApplicationBuilder app) + { + app.UseAuthentication(); + + app.UseMvcWithDefaultRoute(); + } + } +} diff --git a/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilter.cs b/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilter.cs index 4fa7b0e884..01c796512f 100644 --- a/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilter.cs +++ b/test/WebSites/SecurityWebSite/StartupWithGlobalDenyAnonymousFilter.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization.Policy; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Authorization; using Microsoft.Extensions.DependencyInjection; @@ -24,7 +25,8 @@ namespace SecurityWebSite services.AddMvc(o => { o.Filters.Add(new AuthorizeFilter()); - }); + }) + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.AddScoped(); } diff --git a/test/WebSites/SimpleWebSite/Startup.cs b/test/WebSites/SimpleWebSite/Startup.cs index 50ad06a397..a4264f8abb 100644 --- a/test/WebSites/SimpleWebSite/Startup.cs +++ b/test/WebSites/SimpleWebSite/Startup.cs @@ -2,11 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.IO; -using System.Text.Encodings.Web; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.WebEncoders.Testing; using Microsoft.Net.Http.Headers; using Newtonsoft.Json; @@ -21,7 +20,8 @@ namespace SimpleWebSite .AddMvcCore() .AddAuthorization() .AddFormatterMappings(m => m.SetMediaTypeMappingForFormat("js", new MediaTypeHeaderValue("application/json"))) - .AddJsonFormatters(j => j.Formatting = Formatting.Indented); + .AddJsonFormatters(j => j.Formatting = Formatting.Indented) + .SetCompatibilityVersion(CompatibilityVersion.Latest); } public void Configure(IApplicationBuilder app) diff --git a/test/WebSites/TagHelpersWebSite/Startup.cs b/test/WebSites/TagHelpersWebSite/Startup.cs index f6c470b7fc..600b2b6c62 100644 --- a/test/WebSites/TagHelpersWebSite/Startup.cs +++ b/test/WebSites/TagHelpersWebSite/Startup.cs @@ -4,6 +4,7 @@ using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace TagHelpersWebSite @@ -13,7 +14,8 @@ namespace TagHelpersWebSite // Set up application services public void ConfigureServices(IServiceCollection services) { - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); } public void Configure(IApplicationBuilder app) diff --git a/test/WebSites/VersioningWebSite/Startup.cs b/test/WebSites/VersioningWebSite/Startup.cs index 5373436c06..7a94cb2360 100644 --- a/test/WebSites/VersioningWebSite/Startup.cs +++ b/test/WebSites/VersioningWebSite/Startup.cs @@ -1,9 +1,8 @@ // 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.IO; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.DependencyInjection; @@ -14,7 +13,8 @@ namespace VersioningWebSite public void ConfigureServices(IServiceCollection services) { // Add MVC services to the services container - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.AddScoped(); services.AddSingleton(); diff --git a/test/WebSites/VersioningWebSite/StartupWithEndpointRouting.cs b/test/WebSites/VersioningWebSite/StartupWith21Compat.cs similarity index 81% rename from test/WebSites/VersioningWebSite/StartupWithEndpointRouting.cs rename to test/WebSites/VersioningWebSite/StartupWith21Compat.cs index 9c72888db9..44bbc01aa5 100644 --- a/test/WebSites/VersioningWebSite/StartupWithEndpointRouting.cs +++ b/test/WebSites/VersioningWebSite/StartupWith21Compat.cs @@ -1,21 +1,20 @@ // 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.IO; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace VersioningWebSite { - public class StartupWithEndpointRouting + public class StartupWith21Compat { public void ConfigureServices(IServiceCollection services) { // Add MVC services to the services container services.AddMvc() - .AddMvcOptions(options => options.EnableEndpointRouting = true); + .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddScoped(); services.AddSingleton(); diff --git a/test/WebSites/WebApiCompatShimWebSite/Startup.cs b/test/WebSites/WebApiCompatShimWebSite/Startup.cs index 3699ab9e60..b8dda25a9d 100644 --- a/test/WebSites/WebApiCompatShimWebSite/Startup.cs +++ b/test/WebSites/WebApiCompatShimWebSite/Startup.cs @@ -4,6 +4,7 @@ using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace WebApiCompatShimWebSite @@ -13,7 +14,10 @@ namespace WebApiCompatShimWebSite public void ConfigureServices(IServiceCollection services) { // Add MVC services to the services container - services.AddMvc().AddWebApiConventions(); + services.AddMvc() + .AddWebApiConventions() + .SetCompatibilityVersion(CompatibilityVersion.Latest) + .AddMvcOptions(options => options.EnableEndpointRouting = false); } public void Configure(IApplicationBuilder app) diff --git a/test/WebSites/XmlFormattersWebSite/Startup.cs b/test/WebSites/XmlFormattersWebSite/Startup.cs index 31bce95f56..07bda1e37a 100644 --- a/test/WebSites/XmlFormattersWebSite/Startup.cs +++ b/test/WebSites/XmlFormattersWebSite/Startup.cs @@ -17,7 +17,8 @@ namespace XmlFormattersWebSite public void ConfigureServices(IServiceCollection services) { // Add MVC services to the services container - services.AddMvc(); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Latest); services.Configure(options => {