Modifying RazorViewEngine to create IRazorView instances from service

container
This commit is contained in:
Pranav K 2014-08-19 18:07:49 -07:00
parent f6547d63e8
commit 2dcbbf70b0
8 changed files with 151 additions and 120 deletions

View File

@ -0,0 +1,22 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc.Rendering;
namespace Microsoft.AspNet.Mvc.Razor
{
/// <summary>
/// Represents the contract for an <see cref="IView"/> that executes <see cref="IRazorPage"/> as part of its
/// execution.
/// </summary>
public interface IRazorView : IView
{
/// <summary>
/// Contextualizes the current instance of the <see cref="IRazorView"/> providing it with the
/// <see cref="IRazorPage"/> to execute.
/// </summary>
/// <param name="razorPage">The <see cref="IRazorPage"/> instance to execute.</param>
/// <param name="isPartial">Determines if the view is to be executed as a partial.</param>
void Contextualize(IRazorPage razorPage, bool isPartial);
}
}

View File

@ -234,6 +234,22 @@ namespace Microsoft.AspNet.Mvc.Razor
return string.Format(CultureInfo.CurrentCulture, GetString("ViewContextMustBeSet"), p0, p1); return string.Format(CultureInfo.CurrentCulture, GetString("ViewContextMustBeSet"), p0, p1);
} }
/// <summary>
/// The '{0}' method must be called before '{1}' can be invoked.
/// </summary>
internal static string ViewMustBeContextualized
{
get { return GetString("ViewMustBeContextualized"); }
}
/// <summary>
/// The '{0}' method must be called before '{1}' can be invoked.
/// </summary>
internal static string FormatViewMustBeContextualized(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ViewMustBeContextualized"), p0, p1);
}
/// <summary> /// <summary>
/// The method '{0}' cannot be invoked by this view. /// The method '{0}' cannot be invoked by this view.
/// </summary> /// </summary>

View File

@ -3,56 +3,61 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Rendering;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
/// <summary> /// <summary>
/// Represents a <see cref="IView"/> that executes one or more <see cref="RazorPage"/> instances as part of /// Default implementation for <see cref="IRazorView"/> that executes one or more <see cref="RazorPage"/>
/// view rendering. /// instances as part of view rendering.
/// </summary> /// </summary>
public class RazorView : IView public class RazorView : IRazorView
{ {
private readonly IRazorPageFactory _pageFactory; private readonly IRazorPageFactory _pageFactory;
private readonly IRazorPageActivator _pageActivator; private readonly IRazorPageActivator _pageActivator;
private readonly IViewStartProvider _viewStartProvider; private readonly IViewStartProvider _viewStartProvider;
private readonly IRazorPage _page; private IRazorPage _razorPage;
private bool _isPartial;
/// <summary> /// <summary>
/// Initializes a new instance of RazorView /// Initializes a new instance of RazorView
/// </summary> /// </summary>
/// <param name="page">The page to execute</param>
/// <param name="pageFactory">The view factory used to instantiate layout and _ViewStart pages.</param> /// <param name="pageFactory">The view factory used to instantiate layout and _ViewStart pages.</param>
/// <param name="pageActivator">The <see cref="IRazorPageActivator"/> used to activate pages.</param> /// <param name="pageActivator">The <see cref="IRazorPageActivator"/> used to activate pages.</param>
public RazorView([NotNull] IRazorPageFactory pageFactory, /// <param name="viewStartProvider">The <see cref="IViewStartProvider"/> used for discovery of _ViewStart
[NotNull] IRazorPageActivator pageActivator, /// pages</param>
[NotNull] IViewStartProvider viewStartProvider, public RazorView(IRazorPageFactory pageFactory,
[NotNull] IRazorPage page) IRazorPageActivator pageActivator,
IViewStartProvider viewStartProvider)
{ {
_pageFactory = pageFactory; _pageFactory = pageFactory;
_pageActivator = pageActivator; _pageActivator = pageActivator;
_viewStartProvider = viewStartProvider; _viewStartProvider = viewStartProvider;
_page = page;
} }
/// <summary> /// <inheritdoc />
/// Gets or sets a value that determines if the view hierarchy is executed as part of public virtual void Contextualize(IRazorPage razorPage, bool isPartial)
/// executing the <see cref="IRazorPage"/> instance. The view hierarchy involves _ViewStart {
/// and Layout pages. _razorPage = razorPage;
/// </summary> _isPartial = isPartial;
public bool ExecuteViewHierarchy { get; set; } }
/// <inheritdoc /> /// <inheritdoc />
public virtual async Task RenderAsync([NotNull] ViewContext context) public virtual async Task RenderAsync([NotNull] ViewContext context)
{ {
if (ExecuteViewHierarchy) if (_razorPage == null)
{ {
var bodyWriter = await RenderPageAsync(_page, context, executeViewStart: true); var message = Resources.FormatViewMustBeContextualized(nameof(Contextualize), nameof(RenderAsync));
throw new InvalidOperationException(message);
}
if (!_isPartial)
{
var bodyWriter = await RenderPageAsync(_razorPage, context, executeViewStart: true);
await RenderLayoutAsync(context, bodyWriter); await RenderLayoutAsync(context, bodyWriter);
} }
else else
{ {
await RenderPageCoreAsync(_page, context); await RenderPageCoreAsync(_razorPage, context);
} }
} }
@ -93,14 +98,14 @@ namespace Microsoft.AspNet.Mvc.Razor
private async Task RenderViewStartAsync(ViewContext context) private async Task RenderViewStartAsync(ViewContext context)
{ {
var viewStarts = _viewStartProvider.GetViewStartPages(_page.Path); var viewStarts = _viewStartProvider.GetViewStartPages(_razorPage.Path);
foreach (var viewStart in viewStarts) foreach (var viewStart in viewStarts)
{ {
await RenderPageCoreAsync(viewStart, context); await RenderPageCoreAsync(viewStart, context);
// Copy over interesting properties from the ViewStart page to the entry page. // Copy over interesting properties from the ViewStart page to the entry page.
_page.Layout = viewStart.Layout; _razorPage.Layout = viewStart.Layout;
} }
} }
@ -109,7 +114,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
// A layout page can specify another layout page. We'll need to continue // A layout page can specify another layout page. We'll need to continue
// looking for layout pages until they're no longer specified. // looking for layout pages until they're no longer specified.
var previousPage = _page; var previousPage = _razorPage;
while (!string.IsNullOrEmpty(previousPage.Layout)) while (!string.IsNullOrEmpty(previousPage.Layout))
{ {
var layoutPage = _pageFactory.CreateInstance(previousPage.Layout); var layoutPage = _pageFactory.CreateInstance(previousPage.Layout);

View File

@ -31,23 +31,14 @@ namespace Microsoft.AspNet.Mvc.Razor
}; };
private readonly IRazorPageFactory _pageFactory; private readonly IRazorPageFactory _pageFactory;
private readonly ITypeActivator _typeActivator;
private readonly IServiceProvider _serviceProvider;
/// <summary> /// <summary>
/// Initializes a new instance of the RazorViewEngine class. /// Initializes a new instance of the <see cref="RazorViewEngine" /> class.
/// </summary> /// </summary>
/// <param name="pageFactory">The page factory used for creating <see cref="IRazorPage"/>.</param> /// <param name="pageFactory">The page factory used for creating <see cref="IRazorPage"/> instances.</param>
/// <param name="pageActivator">Activator for activated instances of <see cref="IRazorPage"/>.</param> public RazorViewEngine(IRazorPageFactory pageFactory)
/// <param name="viewStartProvider">The provider used to provide instances of ViewStarts applicable to the
/// page being rendered.</param>
public RazorViewEngine(IRazorPageFactory pageFactory,
ITypeActivator typeActivator,
IServiceProvider serviceProvider)
{ {
_pageFactory = pageFactory; _pageFactory = pageFactory;
_typeActivator = typeActivator;
_serviceProvider = serviceProvider;
} }
public IEnumerable<string> ViewLocationFormats public IEnumerable<string> ViewLocationFormats
@ -83,7 +74,7 @@ namespace Microsoft.AspNet.Mvc.Razor
var page = _pageFactory.CreateInstance(viewName); var page = _pageFactory.CreateInstance(viewName);
if (page != null) if (page != null)
{ {
return CreateFoundResult(page, viewName, partial); return CreateFoundResult(context, page, viewName, partial);
} }
} }
return ViewEngineResult.NotFound(viewName, new[] { viewName }); return ViewEngineResult.NotFound(viewName, new[] { viewName });
@ -100,7 +91,7 @@ namespace Microsoft.AspNet.Mvc.Razor
var page = _pageFactory.CreateInstance(path); var page = _pageFactory.CreateInstance(path);
if (page != null) if (page != null)
{ {
return CreateFoundResult(page, path, partial); return CreateFoundResult(context, page, path, partial);
} }
} }
@ -108,10 +99,17 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
} }
private ViewEngineResult CreateFoundResult(IRazorPage page, string viewName, bool partial) private ViewEngineResult CreateFoundResult(ActionContext actionContext,
IRazorPage page,
string viewName,
bool partial)
{ {
var view = _typeActivator.CreateInstance<RazorView>(_serviceProvider, page); // A single request could result in creating multiple IRazorView instances (for partials, view components)
view.ExecuteViewHierarchy = !partial; // and might store state. We'll use the service container to create new instances as we require.
var services = actionContext.HttpContext.RequestServices;
var view = services.GetService<IRazorView>();
view.Contextualize(page, partial);
return ViewEngineResult.Found(viewName, view); return ViewEngineResult.Found(viewName, view);
} }

View File

@ -159,6 +159,9 @@
<data name="ViewContextMustBeSet" xml:space="preserve"> <data name="ViewContextMustBeSet" xml:space="preserve">
<value>'{0} must be set to access '{1}'.</value> <value>'{0} must be set to access '{1}'.</value>
</data> </data>
<data name="ViewMustBeContextualized" xml:space="preserve">
<value>The '{0}' method must be called before '{1}' can be invoked.</value>
</data>
<data name="View_MethodCannotBeCalled" xml:space="preserve"> <data name="View_MethodCannotBeCalled" xml:space="preserve">
<value>The method '{0}' cannot be invoked by this view.</value> <value>The method '{0}' cannot be invoked by this view.</value>
</data> </data>

View File

@ -50,6 +50,7 @@ namespace Microsoft.AspNet.Mvc
yield return describe.Singleton<IViewEngineProvider, DefaultViewEngineProvider>(); yield return describe.Singleton<IViewEngineProvider, DefaultViewEngineProvider>();
yield return describe.Scoped<ICompositeViewEngine, CompositeViewEngine>(); yield return describe.Scoped<ICompositeViewEngine, CompositeViewEngine>();
yield return describe.Singleton<IViewStartProvider, ViewStartProvider>(); yield return describe.Singleton<IViewStartProvider, ViewStartProvider>();
yield return describe.Transient<IRazorView, RazorView>();
yield return describe.Singleton<IRazorPageActivator, RazorPageActivator>(); yield return describe.Singleton<IRazorPageActivator, RazorPageActivator>();
// Virtual path view factory needs to stay scoped so views can get get scoped services. // Virtual path view factory needs to stay scoped so views can get get scoped services.

View File

@ -3,10 +3,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection;
using Moq; using Moq;
using Xunit; using Xunit;
@ -183,17 +182,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
var page = Mock.Of<IRazorPage>(); var page = Mock.Of<IRazorPage>();
pageFactory.Setup(p => p.CreateInstance(It.IsAny<string>())) pageFactory.Setup(p => p.CreateInstance(It.IsAny<string>()))
.Returns(Mock.Of<IRazorPage>()); .Returns(Mock.Of<IRazorPage>());
var viewEngine = new RazorViewEngine(pageFactory.Object);
var serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(p => p.GetService(typeof(IRazorPageFactory)))
.Returns(pageFactory.Object);
serviceProvider.Setup(p => p.GetService(typeof(IRazorPageActivator)))
.Returns(Mock.Of<IRazorPageActivator>());
serviceProvider.Setup(p => p.GetService(typeof(IViewStartProvider)))
.Returns(Mock.Of<IViewStartProvider>());
var viewEngine = new RazorViewEngine(pageFactory.Object,
new TypeActivator(),
serviceProvider.Object);
var context = GetActionContext(_controllerTestContext); var context = GetActionContext(_controllerTestContext);
// Act // Act
@ -201,7 +190,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
// Assert // Assert
Assert.True(result.Success); Assert.True(result.Success);
Assert.IsType<RazorView>(result.View); Assert.IsAssignableFrom<IRazorView>(result.View);
Assert.Equal("/Views/bar/test-view.cshtml", result.ViewName); Assert.Equal("/Views/bar/test-view.cshtml", result.ViewName);
} }
@ -211,16 +200,20 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
pageFactory.Setup(vpf => vpf.CreateInstance(It.IsAny<string>())) pageFactory.Setup(vpf => vpf.CreateInstance(It.IsAny<string>()))
.Returns<RazorPage>(null); .Returns<RazorPage>(null);
var viewEngine = new RazorViewEngine(pageFactory.Object, var viewEngine = new RazorViewEngine(pageFactory.Object);
Mock.Of<ITypeActivator>(),
Mock.Of<IServiceProvider>());
return viewEngine; return viewEngine;
} }
private static ActionContext GetActionContext(IDictionary<string, object> routeValues) private static ActionContext GetActionContext(IDictionary<string, object> routeValues,
IRazorView razorView = null)
{ {
var httpContext = Mock.Of<HttpContext>(); var httpContext = new DefaultHttpContext();
var serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(p => p.GetService(typeof(IRazorView)))
.Returns(razorView ?? Mock.Of<IRazorView>());
httpContext.RequestServices = serviceProvider.Object;
var routeData = new RouteData { Values = routeValues }; var routeData = new RouteData { Values = routeValues };
return new ActionContext(httpContext, routeData, new ActionDescriptor()); return new ActionContext(httpContext, routeData, new ActionDescriptor());
} }

View File

@ -16,7 +16,24 @@ namespace Microsoft.AspNet.Mvc.Razor
private const string LayoutPath = "~/Shared/_Layout.cshtml"; private const string LayoutPath = "~/Shared/_Layout.cshtml";
[Fact] [Fact]
public async Task RenderAsync_WithoutHierarchy_DoesNotCreateOutputBuffer() public async Task RenderAsync_ThrowsIfContextualizeHasNotBeenInvoked()
{
// Arrange
var page = new TestableRazorPage(v => { });
var view = new RazorView(Mock.Of<IRazorPageFactory>(),
Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider());
var viewContext = CreateViewContext(view);
var expected = viewContext.Writer;
// Act and Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => view.RenderAsync(viewContext));
Assert.Equal("The 'Contextualize' method must be called before 'RenderAsync' can be invoked.",
ex.Message);
}
[Fact]
public async Task RenderAsync_AsPartial_DoesNotCreateOutputBuffer()
{ {
// Arrange // Arrange
TextWriter actual = null; TextWriter actual = null;
@ -27,8 +44,8 @@ namespace Microsoft.AspNet.Mvc.Razor
}); });
var view = new RazorView(Mock.Of<IRazorPageFactory>(), var view = new RazorView(Mock.Of<IRazorPageFactory>(),
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider());
page); view.Contextualize(page, isPartial: true);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
var expected = viewContext.Writer; var expected = viewContext.Writer;
@ -41,7 +58,7 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
[Fact] [Fact]
public async Task RenderAsync_WithoutHierarchy_ActivatesViews_WithThePassedInViewContext() public async Task RenderAsync_AsPartial_ActivatesViews_WithThePassedInViewContext()
{ {
// Arrange // Arrange
var viewData = new ViewDataDictionary(Mock.Of<IModelMetadataProvider>()); var viewData = new ViewDataDictionary(Mock.Of<IModelMetadataProvider>());
@ -54,8 +71,8 @@ namespace Microsoft.AspNet.Mvc.Razor
var view = new RazorView(Mock.Of<IRazorPageFactory>(), var view = new RazorView(Mock.Of<IRazorPageFactory>(),
activator.Object, activator.Object,
CreateViewStartProvider(), CreateViewStartProvider());
page); view.Contextualize(page, isPartial: true);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
var expectedWriter = viewContext.Writer; var expectedWriter = viewContext.Writer;
activator.Setup(a => a.Activate(page, It.IsAny<ViewContext>())) activator.Setup(a => a.Activate(page, It.IsAny<ViewContext>()))
@ -75,7 +92,7 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
[Fact] [Fact]
public async Task RenderAsync_WithoutHierarchy_ActivatesViews() public async Task RenderAsync_AsPartial_ActivatesViews()
{ {
// Arrange // Arrange
var page = new TestableRazorPage(v => { }); var page = new TestableRazorPage(v => { });
@ -84,8 +101,8 @@ namespace Microsoft.AspNet.Mvc.Razor
.Verifiable(); .Verifiable();
var view = new RazorView(Mock.Of<IRazorPageFactory>(), var view = new RazorView(Mock.Of<IRazorPageFactory>(),
activator.Object, activator.Object,
CreateViewStartProvider(), CreateViewStartProvider());
page); view.Contextualize(page, isPartial: true);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
// Act // Act
@ -96,7 +113,7 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
[Fact] [Fact]
public async Task RenderAsync_WithoutHierarchy_DoesNotExecuteLayoutOrViewStartPages() public async Task RenderAsync_AsPartial_DoesNotExecuteLayoutOrViewStartPages()
{ {
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
{ {
@ -106,8 +123,8 @@ namespace Microsoft.AspNet.Mvc.Razor
var viewStartProvider = CreateViewStartProvider(); var viewStartProvider = CreateViewStartProvider();
var view = new RazorView(pageFactory.Object, var view = new RazorView(pageFactory.Object,
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
viewStartProvider, viewStartProvider);
page); view.Contextualize(page, isPartial: true);
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
// Act // Act
@ -119,7 +136,7 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
[Fact] [Fact]
public async Task RenderAsync_WithHierarchy_CreatesOutputBuffer() public async Task RenderAsync_CreatesOutputBuffer()
{ {
// Arrange // Arrange
TextWriter actual = null; TextWriter actual = null;
@ -129,11 +146,8 @@ namespace Microsoft.AspNet.Mvc.Razor
}); });
var view = new RazorView(Mock.Of<IRazorPageFactory>(), var view = new RazorView(Mock.Of<IRazorPageFactory>(),
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider());
page) view.Contextualize(page, isPartial: false);
{
ExecuteViewHierarchy = true
};
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
var original = viewContext.Writer; var original = viewContext.Writer;
@ -146,7 +160,7 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
[Fact] [Fact]
public async Task RenderAsync_WithHierarchy_CopiesBufferedContentToOutput() public async Task RenderAsync_CopiesBufferedContentToOutput()
{ {
// Arrange // Arrange
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
@ -155,11 +169,8 @@ namespace Microsoft.AspNet.Mvc.Razor
}); });
var view = new RazorView(Mock.Of<IRazorPageFactory>(), var view = new RazorView(Mock.Of<IRazorPageFactory>(),
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider());
page) view.Contextualize(page, isPartial: false);
{
ExecuteViewHierarchy = true
};
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
var original = viewContext.Writer; var original = viewContext.Writer;
@ -171,7 +182,7 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
[Fact] [Fact]
public async Task RenderAsync_WithHierarchy_ActivatesPages() public async Task RenderAsync_ActivatesPages()
{ {
// Arrange // Arrange
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
@ -183,12 +194,9 @@ namespace Microsoft.AspNet.Mvc.Razor
.Verifiable(); .Verifiable();
var view = new RazorView(Mock.Of<IRazorPageFactory>(), var view = new RazorView(Mock.Of<IRazorPageFactory>(),
activator.Object, activator.Object,
CreateViewStartProvider(), CreateViewStartProvider());
page) view.Contextualize(page, isPartial: false);
{
ExecuteViewHierarchy = true
};
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
// Act // Act
@ -199,7 +207,7 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
[Fact] [Fact]
public async Task RenderAsync_WithHierarchy_ExecutesViewStart() public async Task RenderAsync_ExecutesViewStart()
{ {
// Arrange // Arrange
var actualLayoutPath = ""; var actualLayoutPath = "";
@ -228,11 +236,8 @@ namespace Microsoft.AspNet.Mvc.Razor
.Verifiable(); .Verifiable();
var view = new RazorView(Mock.Of<IRazorPageFactory>(), var view = new RazorView(Mock.Of<IRazorPageFactory>(),
activator.Object, activator.Object,
CreateViewStartProvider(viewStart1, viewStart2), CreateViewStartProvider(viewStart1, viewStart2));
page) view.Contextualize(page, isPartial: false);
{
ExecuteViewHierarchy = true
};
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
// Act // Act
@ -243,7 +248,7 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
[Fact] [Fact]
public async Task RenderAsync_WithHierarchy_ExecutesLayoutPages() public async Task RenderAsync_ExecutesLayoutPages()
{ {
// Arrange // Arrange
var expected = var expected =
@ -285,11 +290,8 @@ foot-content";
var view = new RazorView(pageFactory.Object, var view = new RazorView(pageFactory.Object,
activator.Object, activator.Object,
CreateViewStartProvider(), CreateViewStartProvider());
page) view.Contextualize(page, isPartial: false);
{
ExecuteViewHierarchy = true
};
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
// Act // Act
@ -302,7 +304,7 @@ foot-content";
} }
[Fact] [Fact]
public async Task RenderAsync_WithHierarchy_ThrowsIfSectionsWereDefinedButNotRendered() public async Task RenderAsync_ThrowsIfSectionsWereDefinedButNotRendered()
{ {
// Arrange // Arrange
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
@ -321,11 +323,8 @@ foot-content";
var view = new RazorView(pageFactory.Object, var view = new RazorView(pageFactory.Object,
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider());
page) view.Contextualize(page, isPartial: false);
{
ExecuteViewHierarchy = true
};
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
// Act and Assert // Act and Assert
@ -334,7 +333,7 @@ foot-content";
} }
[Fact] [Fact]
public async Task RenderAsync_WithHierarchy_ThrowsIfBodyWasNotRendered() public async Task RenderAsync_ThrowsIfBodyWasNotRendered()
{ {
// Arrange // Arrange
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
@ -350,11 +349,8 @@ foot-content";
var view = new RazorView(pageFactory.Object, var view = new RazorView(pageFactory.Object,
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider());
page) view.Contextualize(page, isPartial: false);
{
ExecuteViewHierarchy = true
};
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
// Act and Assert // Act and Assert
@ -363,7 +359,7 @@ foot-content";
} }
[Fact] [Fact]
public async Task RenderAsync_WithHierarchy_ExecutesNestedLayoutPages() public async Task RenderAsync_ExecutesNestedLayoutPages()
{ {
// Arrange // Arrange
var expected = var expected =
@ -407,11 +403,8 @@ body-content";
var view = new RazorView(pageFactory.Object, var view = new RazorView(pageFactory.Object,
Mock.Of<IRazorPageActivator>(), Mock.Of<IRazorPageActivator>(),
CreateViewStartProvider(), CreateViewStartProvider());
page) view.Contextualize(page, isPartial: false);
{
ExecuteViewHierarchy = true
};
var viewContext = CreateViewContext(view); var viewContext = CreateViewContext(view);
// Act // Act