// 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 System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Internal;
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();
AddViewComponentApplicationPartsProviders(builder.PartManager);
AddViewServices(builder.Services);
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())
{
manager.FeatureProviders.Add(new ViewComponentFeatureProvider());
}
}
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));
}
AddViews(builder);
builder.Services.Configure(setupAction);
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)
{
throw new ArgumentNullException(nameof(builder));
}
if (setupAction == null)
{
throw new ArgumentNullException(nameof(setupAction));
}
AddCookieTempDataProvider(builder);
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, MvcViewOptionsConfigureCompatibilityOptions>());
services.TryAddEnumerable(
ServiceDescriptor.Transient, TempDataMvcOptionsSetup>());
//
// View Engine and related infrastructure
//
services.TryAddSingleton();
services.TryAddSingleton, ViewResultExecutor>();
services.TryAddSingleton, PartialViewResultExecutor>();
// Support for activating ViewDataDictionary
services.TryAddEnumerable(
ServiceDescriptor
.Transient());
//
// HTML Helper
//
services.TryAddTransient();
services.TryAddTransient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>));
services.TryAddSingleton();
services.TryAddSingleton();
services.TryAddSingleton();
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.TryAddSingleton, ViewComponentResultExecutor>();
services.TryAddSingleton();
services.TryAddTransient();
services.TryAddSingleton();
services.TryAddTransient();
//
// Temp Data
//
services.TryAddEnumerable(
ServiceDescriptor.Transient());
services.TryAddEnumerable(
ServiceDescriptor.Transient());
services.TryAddSingleton();
services.TryAddTransient();
// 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(ArrayPool.Shared);
services.TryAddScoped();
}
}
}