// 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.Buffers; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewComponents; using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection { public static class MvcViewFeaturesMvcCoreBuilderExtensions { public static IMvcCoreBuilder AddViews(this IMvcCoreBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.AddDataAnnotations(); AddViewServices(builder.Services); return builder; } public static IMvcCoreBuilder AddViews( this IMvcCoreBuilder builder, Action setupAction) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (setupAction == null) { throw new ArgumentNullException(nameof(setupAction)); } builder.AddDataAnnotations(); AddViewServices(builder.Services); if (setupAction != null) { builder.Services.Configure(setupAction); } return builder; } public static IMvcCoreBuilder ConfigureViews( this IMvcCoreBuilder builder, Action setupAction) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (setupAction == null) { throw new ArgumentNullException(nameof(setupAction)); } builder.Services.Configure(setupAction); return builder; } // Internal for testing. internal static void AddViewServices(IServiceCollection services) { services.AddDataProtection(); services.AddAntiforgery(); services.AddWebEncoders(); services.TryAddEnumerable( ServiceDescriptor.Transient, MvcViewOptionsSetup>()); services.TryAddEnumerable( ServiceDescriptor.Transient, TempDataMvcOptionsSetup>()); // // View Engine and related infrastructure // services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); // Support for activating ViewDataDictionary services.TryAddEnumerable( ServiceDescriptor .Transient()); // // HTML Helper // services.TryAddTransient(); services.TryAddTransient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>)); services.TryAddSingleton(); // // JSON Helper // services.TryAddSingleton(); services.TryAdd(ServiceDescriptor.Singleton(serviceProvider => { var options = serviceProvider.GetRequiredService>().Value; var charPool = serviceProvider.GetRequiredService>(); return new JsonOutputFormatter(options.SerializerSettings, charPool); })); // // View Components // // These do caching so they should stay singleton services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton< IViewComponentDescriptorCollectionProvider, DefaultViewComponentDescriptorCollectionProvider>(); services.TryAddTransient(); services.TryAddSingleton(); services.TryAddTransient(); // // Temp Data // // This does caching so it should stay singleton services.TryAddSingleton(); // // Antiforgery // services.TryAddSingleton(); services.TryAddSingleton(); // These are stateless so their lifetime isn't really important. services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(ArrayPool.Shared); services.TryAddScoped(); } } }