|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#nullable enable
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
/// <summary>
/// A <see cref="IActionDescriptorProvider"/> for build-time compiled Razor Pages.
/// </summary>
public sealed class CompiledPageActionDescriptorProvider : IActionDescriptorProvider
{
private readonly PageActionDescriptorProvider _pageActionDescriptorProvider;
private readonly ApplicationPartManager _applicationPartManager;
private readonly CompiledPageActionDescriptorFactory _compiledPageActionDescriptorFactory;
/// <summary>
/// Initializes a new instance of <see cref="CompiledPageActionDescriptorProvider"/>.
/// </summary>
/// <param name="pageRouteModelProviders">The sequence of <see cref="IPageRouteModelProvider"/>.</param>
/// <param name="applicationModelProviders">The sequence of <see cref="IPageRouteModelProvider"/>.</param>
/// <param name="applicationPartManager">The <see cref="ApplicationPartManager"/>.</param>
/// <param name="mvcOptions">Accessor to <see cref="MvcOptions"/>.</param>
/// <param name="pageOptions">Accessor to <see cref="RazorPagesOptions"/>.</param>
public CompiledPageActionDescriptorProvider(
IEnumerable<IPageRouteModelProvider> pageRouteModelProviders,
IEnumerable<IPageApplicationModelProvider> applicationModelProviders,
ApplicationPartManager applicationPartManager,
IOptions<MvcOptions> mvcOptions,
IOptions<RazorPagesOptions> pageOptions)
{
_pageActionDescriptorProvider = new PageActionDescriptorProvider(pageRouteModelProviders, mvcOptions, pageOptions);
_applicationPartManager = applicationPartManager;
_compiledPageActionDescriptorFactory = new CompiledPageActionDescriptorFactory(applicationModelProviders, mvcOptions.Value, pageOptions.Value);
}
/// <inheritdoc/>
public int Order => _pageActionDescriptorProvider.Order;
/// <inheritdoc/>
public void OnProvidersExecuting(ActionDescriptorProviderContext context)
{
var newContext = new ActionDescriptorProviderContext();
_pageActionDescriptorProvider.OnProvidersExecuting(newContext);
_pageActionDescriptorProvider.OnProvidersExecuted(newContext);
var feature = new ViewsFeature();
_applicationPartManager.PopulateFeature(feature);
var lookup = new Dictionary<string, CompiledViewDescriptor>(feature.ViewDescriptors.Count, StringComparer.Ordinal);
foreach (var viewDescriptor in feature.ViewDescriptors)
{
// View ordering has precedence semantics, a view with a higher precedence was not
// already added to the list.
lookup.TryAdd(ViewPath.NormalizePath(viewDescriptor.RelativePath), viewDescriptor);
}
foreach (var item in newContext.Results)
{
var pageActionDescriptor = (PageActionDescriptor)item;
if (!lookup.TryGetValue(pageActionDescriptor.RelativePath, out var compiledViewDescriptor))
{
throw new InvalidOperationException($"A descriptor for '{pageActionDescriptor.RelativePath}' was not found.");
}
var compiledPageActionDescriptor = _compiledPageActionDescriptorFactory.CreateCompiledDescriptor(
pageActionDescriptor,
compiledViewDescriptor);
context.Results.Add(compiledPageActionDescriptor);
}
}
/// <inheritdoc/>
public void OnProvidersExecuted(ActionDescriptorProviderContext context)
{
}
}
|