-
Notifications
You must be signed in to change notification settings - Fork 9.8k
/
MvcRazorPagesMvcCoreBuilderExtensions.cs
156 lines (129 loc) · 7.26 KB
/
MvcRazorPagesMvcCoreBuilderExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Resources = Microsoft.AspNetCore.Mvc.RazorPages.Resources;
namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
/// Static class that adds razor page functionality to <see cref="IMvcCoreBuilder"/>.
/// </summary>
public static class MvcRazorPagesMvcCoreBuilderExtensions
{
/// <summary>
/// Register services needed for Razor Pages.
/// </summary>
/// <param name="builder">The <see cref="IMvcCoreBuilder"/>.</param>
/// <returns>The <see cref="IMvcCoreBuilder"/>.</returns>
[RequiresUnreferencedCode("Razor Pages does not currently support trimming or native AOT.", Url = "https://aka.ms/aspnet/trimming")]
public static IMvcCoreBuilder AddRazorPages(this IMvcCoreBuilder builder)
{
ArgumentNullException.ThrowIfNull(builder);
builder.AddRazorViewEngine();
AddRazorPagesServices(builder.Services);
return builder;
}
/// <summary>
/// Register services needed for Razor Pages.
/// </summary>
/// <param name="builder">The <see cref="IMvcCoreBuilder"/>.</param>
/// <param name="setupAction">The action to setup the <see cref="RazorPagesOptions"/>.</param>
/// <returns>The <see cref="IMvcCoreBuilder"/>.</returns>
public static IMvcCoreBuilder AddRazorPages(
this IMvcCoreBuilder builder,
Action<RazorPagesOptions> setupAction)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(setupAction);
builder.AddRazorViewEngine();
AddRazorPagesServices(builder.Services);
builder.Services.Configure(setupAction);
return builder;
}
/// <summary>
/// Configures Razor Pages to use the specified <paramref name="rootDirectory"/>.
/// </summary>
/// <param name="builder">The <see cref="IMvcCoreBuilder"/>.</param>
/// <param name="rootDirectory">The application relative path to use as the root directory.</param>
/// <returns></returns>
public static IMvcCoreBuilder WithRazorPagesRoot(this IMvcCoreBuilder builder, string rootDirectory)
{
ArgumentNullException.ThrowIfNull(builder);
if (string.IsNullOrEmpty(rootDirectory))
{
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(rootDirectory));
}
builder.Services.Configure<RazorPagesOptions>(options => options.RootDirectory = rootDirectory);
return builder;
}
// Internal for testing.
internal static void AddRazorPagesServices(IServiceCollection services)
{
// Options
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorPagesRazorViewEngineOptionsSetup>());
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<RazorPagesOptions>, RazorPagesOptionsSetup>());
// Routing
services.TryAddEnumerable(ServiceDescriptor.Singleton<MatcherPolicy, DynamicPageEndpointMatcherPolicy>());
services.TryAddSingleton<DynamicPageEndpointSelectorCache>();
services.TryAddSingleton<PageActionEndpointDataSourceIdProvider>();
// Action description and invocation
var actionDescriptorProvider = services.FirstOrDefault(f =>
f.ServiceType == typeof(IActionDescriptorProvider) &&
f.ImplementationType == typeof(PageActionDescriptorProvider));
if (actionDescriptorProvider is null)
{
// RuntimeCompilation registers an instance of PageActionDescriptorProvider (PageADP). CompiledPageADP and runtime compilation
// cannot co-exist since CompiledPageADP will attempt to resolve action descriptors for lazily compiled views (such as for
// ones from non-physical file providers). We'll instead avoid adding it if PageADP is already registered. Similarly,
// AddRazorRuntimeCompilation will remove CompiledPageADP if it is registered.
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IActionDescriptorProvider, CompiledPageActionDescriptorProvider>());
}
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPageRouteModelProvider, CompiledPageRouteModelProvider>());
services.TryAddSingleton<PageActionEndpointDataSourceFactory>();
services.TryAddEnumerable(ServiceDescriptor.Singleton<MatcherPolicy, DynamicPageEndpointMatcherPolicy>());
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPageApplicationModelProvider, DefaultPageApplicationModelProvider>());
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPageApplicationModelProvider, AutoValidateAntiforgeryPageApplicationModelProvider>());
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPageApplicationModelProvider, AuthorizationPageApplicationModelProvider>());
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPageApplicationModelProvider, TempDataFilterPageApplicationModelProvider>());
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPageApplicationModelProvider, ViewDataAttributePageApplicationModelProvider>());
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPageApplicationModelProvider, ResponseCacheFilterApplicationModelProvider>());
services.TryAddSingleton<IPageApplicationModelPartsProvider, DefaultPageApplicationModelPartsProvider>();
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IActionInvokerProvider, PageActionInvokerProvider>());
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IRequestDelegateFactory, PageRequestDelegateFactory>());
services.TryAddSingleton<PageActionInvokerCache>();
// Page and Page model creation and activation
services.TryAddSingleton<IPageModelActivatorProvider, DefaultPageModelActivatorProvider>();
services.TryAddSingleton<IPageModelFactoryProvider, DefaultPageModelFactoryProvider>();
services.TryAddSingleton<IPageActivatorProvider, DefaultPageActivatorProvider>();
services.TryAddSingleton<IPageFactoryProvider, DefaultPageFactoryProvider>();
#pragma warning disable CS0618 // Type or member is obsolete
services.TryAddSingleton<IPageLoader>(s => s.GetRequiredService<PageLoader>());
#pragma warning restore CS0618 // Type or member is obsolete
services.TryAddSingleton<PageLoader, DefaultPageLoader>();
services.TryAddSingleton<IPageHandlerMethodSelector, DefaultPageHandlerMethodSelector>();
// Action executors
services.TryAddSingleton<PageResultExecutor>();
services.TryAddTransient<PageSaveTempDataPropertyFilter>();
}
}