diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcBuilderExtensions.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcBuilderExtensions.cs index 3ba1879aa3..78118f01de 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcBuilderExtensions.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ViewComponents; +using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.DependencyInjection.Extensions; namespace Microsoft.Extensions.DependencyInjection @@ -18,7 +19,9 @@ namespace Microsoft.Extensions.DependencyInjection /// Adds configuration of for the application. /// /// The . - /// The which need to be configured. + /// + /// An to configure the provided . + /// /// The . public static IMvcBuilder AddViewOptions( this IMvcBuilder builder, @@ -62,5 +65,57 @@ namespace Microsoft.Extensions.DependencyInjection return builder; } + + /// + /// Registers as the default in the + /// . + /// + /// The . + /// The . + public static IMvcBuilder AddCookieTempDataProvider(this IMvcBuilder builder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + // Ensure the TempData basics are registered. + MvcViewFeaturesMvcCoreBuilderExtensions.AddViewServices(builder.Services); + + var descriptor = ServiceDescriptor.Singleton(typeof(ITempDataProvider), typeof(CookieTempDataProvider)); + builder.Services.Replace(descriptor); + + return builder; + } + + /// + /// Registers as the default in the + /// . + /// + /// The . + /// + /// An to configure the provided + /// . + /// + /// The . + public static IMvcBuilder AddCookieTempDataProvider( + this IMvcBuilder builder, + Action setupAction) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (setupAction == null) + { + throw new ArgumentNullException(nameof(setupAction)); + } + + AddCookieTempDataProvider(builder); + builder.Services.Configure(setupAction); + + return builder; + } } } diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs index 87307afcd3..25452fc589 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs @@ -33,6 +33,28 @@ namespace Microsoft.Extensions.DependencyInjection return builder; } + /// + /// Registers as the default in the + /// . Also registers the default view services. + /// + /// The . + /// The . + public static IMvcCoreBuilder AddCookieTempDataProvider(this IMvcCoreBuilder builder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + // Ensure the TempData basics are registered. + AddViewServices(builder.Services); + + var descriptor = ServiceDescriptor.Singleton(typeof(ITempDataProvider), typeof(CookieTempDataProvider)); + builder.Services.Replace(descriptor); + + return builder; + } + private static void AddViewComponentApplicationPartsProviders(ApplicationPartManager manager) { if (!manager.FeatureProviders.OfType().Any()) @@ -55,14 +77,39 @@ namespace Microsoft.Extensions.DependencyInjection throw new ArgumentNullException(nameof(setupAction)); } - builder.AddDataAnnotations(); - AddViewServices(builder.Services); + AddViews(builder); + builder.Services.Configure(setupAction); - if (setupAction != null) + return builder; + } + + /// + /// Registers as the default in the + /// . Also registers the default view services. + /// + /// The . + /// + /// An to configure the provided + /// . + /// + /// The . + public static IMvcCoreBuilder AddCookieTempDataProvider( + this IMvcCoreBuilder builder, + Action setupAction) + { + if (builder == null) { - builder.Services.Configure(setupAction); + throw new ArgumentNullException(nameof(builder)); } + if (setupAction == null) + { + throw new ArgumentNullException(nameof(setupAction)); + } + + AddCookieTempDataProvider(builder); + builder.Services.Configure(setupAction); + return builder; } diff --git a/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs index 19173f0e02..db7f76d6e9 100644 --- a/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Test/MvcServiceCollectionExtensionsTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Reflection; using Microsoft.AspNetCore.Hosting; @@ -28,13 +29,11 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.ObjectPool; using Microsoft.Extensions.Options; using Moq; using Newtonsoft.Json.Serialization; -using Newtonsoft.Json; using Xunit; -using Microsoft.Extensions.ObjectPool; -using System.Diagnostics; namespace Microsoft.AspNetCore.Mvc { @@ -276,6 +275,35 @@ namespace Microsoft.AspNetCore.Mvc } } + [Fact] + public void AddMvc_RegistersExpectedTempDataProvider() + { + // Arrange + var services = new ServiceCollection(); + + // Act + services.AddMvc(); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(SessionStateTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddMvc_DoesNotRegisterCookieTempDataOptionsConfiguration() + { + // Arrange + var services = new ServiceCollection(); + + // Act + var builder = services.AddMvc(); + + // Assert + Assert.DoesNotContain( + services, + item => item.ServiceType == typeof(IConfigureOptions)); + } + private IEnumerable SingleRegistrationServiceTypes { get diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/DependencyInjection/MvcViewFeaturesMvcBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/DependencyInjection/MvcViewFeaturesMvcBuilderExtensionsTest.cs index 37a887ce36..e8c04b1370 100644 --- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/DependencyInjection/MvcViewFeaturesMvcBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/DependencyInjection/MvcViewFeaturesMvcBuilderExtensionsTest.cs @@ -8,6 +8,8 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ViewComponents; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.Extensions.Options; using Xunit; namespace Microsoft.Extensions.DependencyInjection @@ -35,6 +37,100 @@ namespace Microsoft.Extensions.DependencyInjection Assert.Equal(typeof(ServiceBasedViewComponentActivator), descriptor.ImplementationType); } + [Fact] + public void AddCookieTempDataProvider_RegistersExpectedTempDataProvider() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvc(); + + // Act + builder.AddCookieTempDataProvider(); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProvider_DoesNotRegisterOptionsConfiguration() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvc(); + + // Act + builder.AddCookieTempDataProvider(); + + // Assert + Assert.DoesNotContain( + services, + item => item.ServiceType == typeof(IConfigureOptions)); + } + + [Fact] + public void AddCookieTempDataProviderWithSetupAction_RegistersExpectedTempDataProvider() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvc(); + + // Act + builder.AddCookieTempDataProvider(options => { }); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProviderWithSetupAction_RegistersOptionsConfiguration() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvc(); + + // Act + builder.AddCookieTempDataProvider(options => { }); + + // Assert + Assert.Single( + services, + item => item.ServiceType == typeof(IConfigureOptions)); + } + + [Fact] + public void AddCookieTempDataProvider_RegistersExpectedTempDataProvider_IfCalledTwice() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvc(); + + // Act + builder.AddCookieTempDataProvider(); + builder.AddCookieTempDataProvider(); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProviderWithSetupAction_RegistersExpectedTempDataProvider_IfCalledTwice() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvc(); + + // Act + builder.AddCookieTempDataProvider(options => { }); + builder.AddCookieTempDataProvider(options => { }); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + [Fact] public void AddViewComponentsAsServices_RegistersDiscoveredViewComponents() { diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensionsTest.cs new file mode 100644 index 0000000000..682ea48bc3 --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensionsTest.cs @@ -0,0 +1,186 @@ +// 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; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.Extensions.DependencyInjection +{ + public class MvcViewFeaturesMvcCoreBuilderExtensionsTest + { + [Fact] + public void AddViews_RegistersExpectedTempDataProvider() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddViews(); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(SessionStateTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProvider_RegistersExpectedTempDataProvider() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddCookieTempDataProvider(); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProvider_DoesNotRegisterOptionsConfiguration() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddCookieTempDataProvider(); + + // Assert + Assert.DoesNotContain( + services, + item => item.ServiceType == typeof(IConfigureOptions)); + } + + [Fact] + public void AddCookieTempDataProviderWithSetupAction_RegistersExpectedTempDataProvider() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddCookieTempDataProvider(options => { }); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProviderWithSetupAction_RegistersOptionsConfiguration() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddCookieTempDataProvider(options => { }); + + // Assert + Assert.Single( + services, + item => item.ServiceType == typeof(IConfigureOptions)); + } + + [Fact] + public void AddCookieTempDataProvider_RegistersExpectedTempDataProvider_IfCalledBeforeAddViews() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddCookieTempDataProvider(); + builder.AddViews(); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProviderWithSetupAction_RegistersExpectedTempDataProvider_IfCalledBeforeAddViews() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddCookieTempDataProvider(options => { }); + builder.AddViews(); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProvider_RegistersExpectedTempDataProvider_IfCalledAfterAddViews() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddViews(); + builder.AddCookieTempDataProvider(); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProviderWithSetupAction_RegistersExpectedTempDataProvider_IfCalledAfterAddViews() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddViews(); + builder.AddCookieTempDataProvider(options => { }); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProvider_RegistersExpectedTempDataProvider_IfCalledTwice() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddCookieTempDataProvider(); + builder.AddCookieTempDataProvider(); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + + [Fact] + public void AddCookieTempDataProviderWithSetupAction_RegistersExpectedTempDataProvider_IfCalledTwice() + { + // Arrange + var services = new ServiceCollection(); + var builder = services.AddMvcCore(); + + // Act + builder.AddCookieTempDataProvider(options => { }); + builder.AddCookieTempDataProvider(options => { }); + + // Assert + var descriptor = Assert.Single(services, item => item.ServiceType == typeof(ITempDataProvider)); + Assert.Equal(typeof(CookieTempDataProvider), descriptor.ImplementationType); + } + } +} diff --git a/test/WebSites/BasicWebSite/StartupWithCookieTempDataProvider.cs b/test/WebSites/BasicWebSite/StartupWithCookieTempDataProvider.cs index 5ecaa675c3..eec17b5544 100644 --- a/test/WebSites/BasicWebSite/StartupWithCookieTempDataProvider.cs +++ b/test/WebSites/BasicWebSite/StartupWithCookieTempDataProvider.cs @@ -2,7 +2,6 @@ // 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.ViewFeatures; using Microsoft.Extensions.DependencyInjection; namespace BasicWebSite @@ -11,8 +10,9 @@ namespace BasicWebSite { public void ConfigureServices(IServiceCollection services) { - services.AddMvc(); - services.AddSingleton(); + services + .AddMvc() + .AddCookieTempDataProvider(); } public void Configure(IApplicationBuilder app)