diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllersAsServices.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllersAsServices.cs index df3062fb0f..a6b3985fa1 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllersAsServices.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllersAsServices.cs @@ -26,7 +26,14 @@ namespace Microsoft.AspNetCore.Mvc.Internal throw new ArgumentNullException(nameof(types)); } - var controllerTypeProvider = new StaticControllerTypeProvider(); + StaticControllerTypeProvider controllerTypeProvider = null; + + controllerTypeProvider = services + .Where(s => s.ServiceType == typeof(IControllerTypeProvider)) + .Select(s => s.ImplementationInstance) + .OfType() + .FirstOrDefault() + ?? new StaticControllerTypeProvider(); foreach (var type in types) { diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerAsServicesTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerAsServicesTest.cs new file mode 100644 index 0000000000..22998e7e1c --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerAsServicesTest.cs @@ -0,0 +1,48 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.AspNetCore.Mvc.Internal +{ + public class ControllerAsServicesTest + { + [Fact] + public void AddControllerAsServices_MultipleCalls_RetainsPreviouslyAddedTypes() + { + // Arrange + var services = new ServiceCollection(); + + // Act 1 + ControllersAsServices.AddControllersAsServices(services, new Type[] { typeof(ControllerOne) }); + + // Assert 1 + var serviceDescriptor = Assert.Single(services, s => s.ServiceType == typeof(IControllerTypeProvider)); + var controllerTypeProvider = Assert.IsType(serviceDescriptor.ImplementationInstance); + var expectedControllerType = Assert.Single(controllerTypeProvider.ControllerTypes); + + // Act 2 + ControllersAsServices.AddControllersAsServices(services, new Type[] { typeof(ControllerTwo) }); + + // Assert 2 + serviceDescriptor = Assert.Single(services, s => s.ServiceType == typeof(IControllerTypeProvider)); + controllerTypeProvider = Assert.IsType(serviceDescriptor.ImplementationInstance); + Assert.Equal(2, controllerTypeProvider.ControllerTypes.Count); + Assert.Same(expectedControllerType, controllerTypeProvider.ControllerTypes[0]); + Assert.Same(typeof(ControllerTwo), controllerTypeProvider.ControllerTypes[1]); + } + + private class ControllerOne + { + } + + private class ControllerTwo + { + } + } +} diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ControllerFromServicesTests.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ControllerFromServicesTests.cs index c2c4e57389..58f349d774 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ControllerFromServicesTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/ControllerFromServicesTests.cs @@ -104,5 +104,18 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests // Assert Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } + + [Fact] + public async Task AddControllersAsServices_MultipleCalls_DoesNotReplacePreviousProvider() + { + // Arrange + var expected = "1"; + + // Act + var response = await Client.GetStringAsync("http://localhost/another/"); + + // Assert + Assert.Equal(expected, response); + } } } diff --git a/test/WebSites/ControllersFromServicesWebSite/AnotherController.cs b/test/WebSites/ControllersFromServicesWebSite/AnotherController.cs new file mode 100644 index 0000000000..9277327a06 --- /dev/null +++ b/test/WebSites/ControllersFromServicesWebSite/AnotherController.cs @@ -0,0 +1,17 @@ +// 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.Mvc; + +namespace ControllersFromServicesWebSite +{ + [Route("/[controller]")] + public class AnotherController : Controller + { + [HttpGet] + public int Get() + { + return 1; + } + } +} diff --git a/test/WebSites/ControllersFromServicesWebSite/Startup.cs b/test/WebSites/ControllersFromServicesWebSite/Startup.cs index 83edd12cc9..df2124bac3 100644 --- a/test/WebSites/ControllersFromServicesWebSite/Startup.cs +++ b/test/WebSites/ControllersFromServicesWebSite/Startup.cs @@ -17,6 +17,7 @@ namespace ControllersFromServicesWebSite { services .AddMvc() + .AddControllersAsServices(typeof(AnotherController)) .AddControllersAsServices(new[] { typeof(TimeScheduleController).GetTypeInfo().Assembly