Add support for PageStarts

This commit is contained in:
Pranav K 2017-01-30 16:09:53 -08:00
parent c95c2a5a6d
commit 8d5abd433f
12 changed files with 322 additions and 57 deletions

View File

@ -19,6 +19,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
_provider = provider;
}
public override RazorProjectItem GetItem(string path)
{
EnsureValidPath(path);
var fileInfo = _provider.GetFileInfo(path);
return new DefaultRazorProjectItem(fileInfo, basePath: string.Empty, path: path);
}
public override IEnumerable<RazorProjectItem> EnumerateItems(string path)
{
if (path == null)

View File

@ -22,6 +22,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
public override string Path { get; }
public override bool Exists => _fileInfo.Exists;
public override string PhysicalPath => _fileInfo.PhysicalPath;
public override Stream Read()

View File

@ -0,0 +1,60 @@
// 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.Diagnostics;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
{
/// <summary>
/// Executes a Razor Page.
/// </summary>
public class PageResultExecutor : ViewExecutor
{
private readonly IRazorViewEngine _razorViewEngine;
private readonly IRazorPageActivator _razorPageActivator;
private readonly HtmlEncoder _htmlEncoder;
/// <summary>
/// Creates a new <see cref="PageResultExecutor"/>.
/// </summary>
/// <param name="writerFactory">The <see cref="IHttpResponseStreamWriterFactory"/>.</param>
/// <param name="compositeViewEngine">The <see cref="ICompositeViewEngine"/>.</param>
/// <param name="razorViewEngine">The <see cref="IRazorViewEngine"/>.</param>
/// <param name="razorPageActivator">The <see cref="IRazorPageActivator"/>.</param>
/// <param name="diagnosticSource">The <see cref="DiagnosticSource"/>.</param>
/// <param name="htmlEncoder">The <see cref="HtmlEncoder"/>.</param>
public PageResultExecutor(
IHttpResponseStreamWriterFactory writerFactory,
ICompositeViewEngine compositeViewEngine,
IRazorViewEngine razorViewEngine,
IRazorPageActivator razorPageActivator,
DiagnosticSource diagnosticSource,
HtmlEncoder htmlEncoder)
: base(writerFactory, compositeViewEngine, diagnosticSource)
{
_razorViewEngine = razorViewEngine;
_razorPageActivator = razorPageActivator;
_htmlEncoder = htmlEncoder;
}
/// <summary>
/// Executes a Razor Page asynchronously.
/// </summary>
public virtual Task ExecuteAsync(PageContext pageContext, PageViewResult result)
{
if (result.Model != null)
{
pageContext.ViewData.Model = result.Model;
}
var view = new RazorView(_razorViewEngine, _razorPageActivator, pageContext.PageStarts, result.Page, _htmlEncoder);
return ExecuteAsync(pageContext, result.ContentType, result.StatusCode);
}
}
}

View File

@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.Core.Internal;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.Extensions.Logging;
@ -304,6 +305,23 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
_page = (Page)CacheEntry.PageFactory(_pageContext);
_pageContext.Page = _page;
IRazorPage[] pageStarts;
if (CacheEntry.PageStartFactories == null || CacheEntry.PageStartFactories.Count == 0)
{
pageStarts = EmptyArray<IRazorPage>.Instance;
}
else
{
pageStarts = new IRazorPage[CacheEntry.PageStartFactories.Count];
for (var i = 0; i < pageStarts.Length; i++)
{
var pageFactory = CacheEntry.PageStartFactories[i];
pageStarts[i] = pageFactory();
}
}
_pageContext.PageStarts = pageStarts;
if (actionDescriptor.ModelTypeInfo == null)
{
_model = _page;

View File

@ -2,7 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Razor;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
@ -14,6 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
Action<PageContext, object> releasePage,
Func<PageContext, object> modelFactory,
Action<PageContext, object> releaseModel,
IReadOnlyList<Func<IRazorPage>> pageStartFactories,
FilterItem[] cacheableFilters)
{
ActionDescriptor = actionDescriptor;
@ -21,6 +24,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
ReleasePage = releasePage;
ModelFactory = modelFactory;
ReleaseModel = releaseModel;
PageStartFactories = pageStartFactories;
CacheableFilters = cacheableFilters;
}
@ -35,6 +39,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
public Func<PageContext, object> ModelFactory { get; }
/// <summary>
/// Gets the applicable PageStarts.
/// </summary>
public IReadOnlyList<Func<IRazorPage>> PageStartFactories { get; }
/// <summary>
/// The action invoked to release a model. This may be <c>null</c>.
/// </summary>

View File

@ -12,8 +12,10 @@ using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -21,10 +23,12 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
public class PageActionInvokerProvider : IActionInvokerProvider
{
private const string PageStartFileName = "_PageStart.cshtml";
private const string ModelPropertyName = "Model";
private readonly IPageLoader _loader;
private readonly IPageFactoryProvider _pageFactoryProvider;
private readonly IPageModelFactoryProvider _modelFactoryProvider;
private readonly IRazorPageFactoryProvider _razorPageFactoryProvider;
private readonly IActionDescriptorCollectionProvider _collectionProvider;
private readonly IFilterProvider[] _filterProviders;
private readonly IReadOnlyList<IValueProviderFactory> _valueProviderFactories;
@ -32,6 +36,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
private readonly ITempDataDictionaryFactory _tempDataFactory;
private readonly HtmlHelperOptions _htmlHelperOptions;
private readonly IPageHandlerMethodSelector _selector;
private readonly RazorProject _razorProject;
private readonly DiagnosticSource _diagnosticSource;
private readonly ILogger<PageActionInvoker> _logger;
private volatile InnerCache _currentCache;
@ -40,6 +45,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
IPageLoader loader,
IPageFactoryProvider pageFactoryProvider,
IPageModelFactoryProvider modelFactoryProvider,
IRazorPageFactoryProvider razorPageFactoryProvider,
IActionDescriptorCollectionProvider collectionProvider,
IEnumerable<IFilterProvider> filterProviders,
IEnumerable<IValueProviderFactory> valueProviderFactories,
@ -47,12 +53,14 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
ITempDataDictionaryFactory tempDataFactory,
IOptions<HtmlHelperOptions> htmlHelperOptions,
IPageHandlerMethodSelector selector,
RazorProject razorProject,
DiagnosticSource diagnosticSource,
ILoggerFactory loggerFactory)
{
_loader = loader;
_pageFactoryProvider = pageFactoryProvider;
_modelFactoryProvider = modelFactoryProvider;
_razorPageFactoryProvider = razorPageFactoryProvider;
_collectionProvider = collectionProvider;
_filterProviders = filterProviders.ToArray();
_valueProviderFactories = valueProviderFactories.ToArray();
@ -60,6 +68,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
_tempDataFactory = tempDataFactory;
_htmlHelperOptions = htmlHelperOptions.Value;
_selector = selector;
_razorProject = razorProject;
_diagnosticSource = diagnosticSource;
_logger = loggerFactory.CreateLogger<PageActionInvoker>();
}
@ -171,15 +180,34 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
modelReleaser = _modelFactoryProvider.CreateModelDisposer(compiledActionDescriptor);
}
var pageStartFactories = GetPageStartFactories(compiledActionDescriptor);
return new PageActionInvokerCacheEntry(
compiledActionDescriptor,
pageFactory,
pageDisposer,
modelFactory,
modelReleaser,
pageStartFactories,
cachedFilters);
}
private List<Func<IRazorPage>> GetPageStartFactories(CompiledPageActionDescriptor descriptor)
{
var pageStartFactories = new List<Func<IRazorPage>>();
var pageStartItems = _razorProject.FindHierarchicalItems(descriptor.ViewEnginePath, PageStartFileName);
foreach (var item in pageStartItems)
{
var factoryResult = _razorPageFactoryProvider.CreateFactory(item.Path);
if (factoryResult.Success)
{
pageStartFactories.Insert(0, factoryResult.RazorPageFactory);
}
}
return pageStartFactories;
}
private class InnerCache
{
public InnerCache(int version)

View File

@ -1,21 +0,0 @@
// 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.Threading.Tasks;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
public class PageResultExecutor
{
public virtual Task ExecuteAsync(PageContext pageContext, PageViewResult result)
{
if (result.Model != null)
{
result.Page.PageContext.ViewData.Model = result.Model;
}
throw new NotImplementedException();
}
}
}

View File

@ -2,7 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
@ -72,5 +75,10 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
_page = value;
}
}
/// <summary>
/// Gets or sets the applicable _PageStart instances.
/// </summary>
public IReadOnlyList<IRazorPage> PageStarts { get; set; }
}
}

View File

@ -3,7 +3,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.RazorPages.Internal;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Mvc.RazorPages

View File

@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Internal;
@ -10,7 +11,6 @@ using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Mvc.ViewFeatures
@ -25,8 +25,6 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
/// </summary>
public static readonly string DefaultContentType = "text/html; charset=utf-8";
private readonly IModelMetadataProvider _modelMetadataProvider;
/// <summary>
/// Creates a new <see cref="ViewExecutor"/>.
/// </summary>
@ -43,22 +41,13 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
ITempDataDictionaryFactory tempDataFactory,
DiagnosticSource diagnosticSource,
IModelMetadataProvider modelMetadataProvider)
: this(writerFactory, viewEngine, diagnosticSource)
{
if (viewOptions == null)
{
throw new ArgumentNullException(nameof(viewOptions));
}
if (writerFactory == null)
{
throw new ArgumentNullException(nameof(writerFactory));
}
if (viewEngine == null)
{
throw new ArgumentNullException(nameof(viewEngine));
}
if (tempDataFactory == null)
{
throw new ArgumentNullException(nameof(tempDataFactory));
@ -69,17 +58,40 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
throw new ArgumentNullException(nameof(diagnosticSource));
}
if (modelMetadataProvider == null)
ViewOptions = viewOptions.Value;
TempDataFactory = tempDataFactory;
ModelMetadataProvider = modelMetadataProvider;
}
/// <summary>
/// Creates a new <see cref="ViewExecutor"/>.
/// </summary>
/// <param name="writerFactory">The <see cref="IHttpResponseStreamWriterFactory"/>.</param>
/// <param name="viewEngine">The <see cref="ICompositeViewEngine"/>.</param>
/// <param name="diagnosticSource">The <see cref="System.Diagnostics.DiagnosticSource"/>.</param>
protected ViewExecutor(
IHttpResponseStreamWriterFactory writerFactory,
ICompositeViewEngine viewEngine,
DiagnosticSource diagnosticSource)
{
if (writerFactory == null)
{
throw new ArgumentNullException(nameof(modelMetadataProvider));
throw new ArgumentNullException(nameof(writerFactory));
}
if (viewEngine == null)
{
throw new ArgumentNullException(nameof(viewEngine));
}
if (diagnosticSource == null)
{
throw new ArgumentNullException(nameof(diagnosticSource));
}
ViewOptions = viewOptions.Value;
WriterFactory = writerFactory;
ViewEngine = viewEngine;
TempDataFactory = tempDataFactory;
DiagnosticSource = diagnosticSource;
_modelMetadataProvider = modelMetadataProvider;
}
/// <summary>
@ -102,6 +114,11 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
/// </summary>
protected MvcViewOptions ViewOptions { get; }
/// <summary>
/// Gets the <see cref="IModelMetadataProvider"/>.
/// </summary>
protected IModelMetadataProvider ModelMetadataProvider { get; }
/// <summary>
/// Gets the <see cref="IHttpResponseStreamWriterFactory"/>.
/// </summary>
@ -140,9 +157,24 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
throw new ArgumentNullException(nameof(view));
}
if (ViewOptions == null)
{
throw new InvalidOperationException(Resources.FormatPropertyOfTypeCannotBeNull(nameof(ViewOptions), GetType().Name));
}
if (TempDataFactory == null)
{
throw new InvalidOperationException(Resources.FormatPropertyOfTypeCannotBeNull(nameof(TempDataFactory), GetType().Name));
}
if (ModelMetadataProvider == null)
{
throw new InvalidOperationException(Resources.FormatPropertyOfTypeCannotBeNull(nameof(ModelMetadataProvider), GetType().Name));
}
if (viewData == null)
{
viewData = new ViewDataDictionary(_modelMetadataProvider, actionContext.ModelState);
viewData = new ViewDataDictionary(ModelMetadataProvider, actionContext.ModelState);
}
if (tempData == null)
@ -150,7 +182,40 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
tempData = TempDataFactory.GetTempData(actionContext.HttpContext);
}
var response = actionContext.HttpContext.Response;
var viewContext = new ViewContext(
actionContext,
view,
viewData,
tempData,
TextWriter.Null,
ViewOptions.HtmlHelperOptions);
await ExecuteAsync(viewContext, contentType, statusCode);
}
/// <summary>
/// Executes a view asynchronously.
/// </summary>
/// <param name="viewContext">The <see cref="ViewContext"/> associated with the current request.</param>
/// <param name="contentType">
/// The content-type header value to set in the response. If <c>null</c>,
/// <see cref="DefaultContentType"/> will be used.
/// </param>
/// <param name="statusCode">
/// The HTTP status code to set in the response. May be <c>null</c>.
/// </param>
/// <returns>A <see cref="Task"/> which will complete when view execution is completed.</returns>
protected async Task ExecuteAsync(
ViewContext viewContext,
string contentType,
int? statusCode)
{
if (viewContext == null)
{
throw new ArgumentNullException(nameof(viewContext));
}
var response = viewContext.HttpContext.Response;
string resolvedContentType = null;
Encoding resolvedContentTypeEncoding = null;
@ -170,19 +235,23 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
using (var writer = WriterFactory.CreateWriter(response.Body, resolvedContentTypeEncoding))
{
var viewContext = new ViewContext(
actionContext,
view,
viewData,
tempData,
writer,
ViewOptions.HtmlHelperOptions);
var view = viewContext.View;
DiagnosticSource.BeforeView(view, viewContext);
var oldWriter = viewContext.Writer;
try
{
viewContext.Writer = writer;
await view.RenderAsync(viewContext);
DiagnosticSource.BeforeView(view, viewContext);
DiagnosticSource.AfterView(view, viewContext);
await view.RenderAsync(viewContext);
DiagnosticSource.AfterView(view, viewContext);
}
finally
{
viewContext.Writer = oldWriter;
}
// Perf: Invoke FlushAsync to ensure any buffered content is asynchronously written to the underlying
// response asynchronously. In the absence of this line, the buffer gets synchronously written to the

View File

@ -8,10 +8,14 @@ using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.Primitives;
using Moq;
using Xunit;
@ -120,6 +124,53 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
Assert.Same(modelDisposer, entry.ReleaseModel);
}
[Fact]
public void OnProvidersExecuting_CachesViewStartFactories()
{
// Arrange
var descriptor = new PageActionDescriptor
{
RelativePath = "/Home/Path1/File.cshtml",
ViewEnginePath = "/Home/Path1/File.cshtml",
FilterDescriptors = new FilterDescriptor[0],
};
var loader = new Mock<IPageLoader>();
loader.Setup(l => l.Load(It.IsAny<PageActionDescriptor>()))
.Returns(typeof(PageWithModel));
var descriptorCollection = new ActionDescriptorCollection(new[] { descriptor }, version: 1);
var actionDescriptorProvider = new Mock<IActionDescriptorCollectionProvider>();
actionDescriptorProvider.Setup(p => p.ActionDescriptors).Returns(descriptorCollection);
var razorPageFactoryProvider = new Mock<IRazorPageFactoryProvider>();
Func<IRazorPage> factory1 = () => null;
Func<IRazorPage> factory2 = () => null;
razorPageFactoryProvider.Setup(f => f.CreateFactory("/Home/Path1/_PageStart.cshtml"))
.Returns(new RazorPageFactoryResult(factory1, new IChangeToken[0]));
razorPageFactoryProvider.Setup(f => f.CreateFactory("/_PageStart.cshtml"))
.Returns(new RazorPageFactoryResult(factory2, new[] { Mock.Of<IChangeToken>() }));
var fileProvider = new TestFileProvider();
fileProvider.AddFile("/Home/Path1/_PageStart.cshtml", "content1");
fileProvider.AddFile("/_PageStart.cshtml", "content2");
var defaultRazorProject = new DefaultRazorProject(fileProvider);
var invokerProvider = CreateInvokerProvider(
loader.Object,
actionDescriptorProvider.Object,
razorPageFactoryProvider: razorPageFactoryProvider.Object,
razorProject: defaultRazorProject);
var context = new ActionInvokerProviderContext(
new ActionContext(new DefaultHttpContext(), new RouteData(), descriptor));
// Act
invokerProvider.OnProvidersExecuting(context);
// Assert
Assert.NotNull(context.Result);
var actionInvoker = Assert.IsType<PageActionInvoker>(context.Result);
var entry = actionInvoker.CacheEntry;
Assert.Equal(new[] { factory2, factory1 }, entry.PageStartFactories);
}
[Fact]
public void OnProvidersExecuting_CachesEntries()
{
@ -207,16 +258,24 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
IPageLoader loader,
IActionDescriptorCollectionProvider actionDescriptorProvider,
IPageFactoryProvider pageProvider = null,
IPageModelFactoryProvider modelProvider = null)
IPageModelFactoryProvider modelProvider = null,
IRazorPageFactoryProvider razorPageFactoryProvider = null,
RazorProject razorProject = null)
{
var tempDataFactory = new Mock<ITempDataDictionaryFactory>();
tempDataFactory.Setup(t => t.GetTempData(It.IsAny<HttpContext>()))
.Returns((HttpContext context) => new TempDataDictionary(context, Mock.Of<ITempDataProvider>()));
if (razorProject == null)
{
razorProject = Mock.Of<RazorProject>();
}
return new PageActionInvokerProvider(
loader,
pageProvider ?? Mock.Of<IPageFactoryProvider>(),
modelProvider ?? Mock.Of<IPageModelFactoryProvider>(),
razorPageFactoryProvider ?? Mock.Of<IRazorPageFactoryProvider>(),
actionDescriptorProvider,
new IFilterProvider[0],
new IValueProviderFactory[0],
@ -224,6 +283,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
tempDataFactory.Object,
new TestOptionsManager<HtmlHelperOptions>(),
Mock.Of<IPageHandlerMethodSelector>(),
razorProject,
new DiagnosticListener("Microsoft.AspNetCore"),
NullLoggerFactory.Instance);
}

View File

@ -5,11 +5,15 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
@ -346,6 +350,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
null,
(context) => null,
null,
null,
new FilterItem[0]);
var invoker = CreateInvoker(
new[] { filter1.Object, filter2.Object, filter3.Object },
@ -399,6 +404,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
null,
(context) => null,
null,
null,
new FilterItem[0]);
var invoker = CreateInvoker(
new IFilterMetadata[] { filter1.Object, filter2.Object, filter3.Object },
@ -530,12 +536,24 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
int maxAllowedErrorsInModelState = 200,
List<IValueProviderFactory> valueProviderFactories = null,
RouteData routeData = null,
ILogger logger = null,
object diagnosticListener = null)
ILogger logger = null)
{
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
var httpContext = new DefaultHttpContext();
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton(executor ?? new PageResultExecutor());
if (executor == null)
{
executor = new PageResultExecutor(
Mock.Of<IHttpResponseStreamWriterFactory>(),
Mock.Of<ICompositeViewEngine>(),
Mock.Of<IRazorViewEngine>(),
Mock.Of<IRazorPageActivator>(),
diagnosticSource,
HtmlEncoder.Default);
}
serviceCollection.AddSingleton(executor ?? executor);
httpContext.RequestServices = serviceCollection.BuildServiceProvider();
if (routeData == null)
@ -584,8 +602,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
(c, page) => { (page as IDisposable)?.Dispose(); },
_ => Activator.CreateInstance(actionDescriptor.ModelTypeInfo.AsType()),
(c, model) => { (model as IDisposable)?.Dispose(); },
null,
new FilterItem[0]);
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
var invoker = new PageActionInvoker(
selector,
@ -603,6 +621,13 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
private readonly Func<PageContext, Task> _executeAction;
public TestPageResultExecutor(Func<PageContext, Task> executeAction)
: base(
Mock.Of<IHttpResponseStreamWriterFactory>(),
Mock.Of<ICompositeViewEngine>(),
Mock.Of<IRazorViewEngine>(),
Mock.Of<IRazorPageActivator>(),
new DiagnosticListener("Microsoft.AspNetCore"),
HtmlEncoder.Default)
{
_executeAction = executeAction;
}