From b0c782cdeadc1d05b856a52a4bfb6df77f476bc2 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Fri, 23 Jun 2017 14:36:05 -0700 Subject: [PATCH 1/4] Add DiagnosticSource to RazorView --- .../MvcRazorDiagnosticSourceExtensions.cs | 37 ++++ .../RazorView.cs | 18 +- .../RazorViewEngine.cs | 7 +- .../Infrastructure/PageResultExecutor.cs | 5 +- .../RazorViewEngineTest.cs | 6 +- .../RazorViewTest.cs | 170 ++++++++++++++---- .../IProxyPage.cs | 9 + .../TestDiagnosticListener.cs | 36 ++++ 8 files changed, 248 insertions(+), 40 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs create mode 100644 test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/IProxyPage.cs diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs new file mode 100644 index 0000000000..917962838a --- /dev/null +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs @@ -0,0 +1,37 @@ +// 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 Microsoft.AspNetCore.Mvc.Rendering; + +namespace Microsoft.AspNetCore.Mvc.Razor.Internal +{ + public static class MvcRazorDiagnosticSourceExtensions + { + public static void BeforeRazorView( + this DiagnosticSource diagnosticSource, + IRazorPage page, + ViewContext viewContext) + { + if (diagnosticSource.IsEnabled("Microsoft.AspNetCore.Mvc.Razor.BeforeRazorView")) + { + diagnosticSource.Write( + "Microsoft.AspNetCore.Mvc.Razor.BeforeRazorView", + new { page = page, viewContext = viewContext, }); + } + } + + public static void AfterRazorView( + this DiagnosticSource diagnosticSource, + IRazorPage page, + ViewContext viewContext) + { + if (diagnosticSource.IsEnabled("Microsoft.AspNetCore.Mvc.Razor.AfterRazorView")) + { + diagnosticSource.Write( + "Microsoft.AspNetCore.Mvc.Razor.AfterRazorView", + new { page = page, viewContext = viewContext, }); + } + } + } +} diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs index 19bee46190..63aab535a2 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; +using Microsoft.AspNetCore.Mvc.Razor.Internal; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Mvc.Razor @@ -23,6 +24,7 @@ public class RazorView : IView private readonly IRazorViewEngine _viewEngine; private readonly IRazorPageActivator _pageActivator; private readonly HtmlEncoder _htmlEncoder; + private readonly DiagnosticSource _diagnosticSource; private IViewBufferScope _bufferScope; /// @@ -34,12 +36,14 @@ public class RazorView : IView /// /// The instance to execute. /// The HTML encoder. + /// The . public RazorView( IRazorViewEngine viewEngine, IRazorPageActivator pageActivator, IReadOnlyList viewStartPages, IRazorPage razorPage, - HtmlEncoder htmlEncoder) + HtmlEncoder htmlEncoder, + DiagnosticSource diagnosticSource) { if (viewEngine == null) { @@ -66,11 +70,17 @@ public RazorView( throw new ArgumentNullException(nameof(htmlEncoder)); } + if (diagnosticSource == null) + { + throw new ArgumentNullException(nameof(diagnosticSource)); + } + _viewEngine = viewEngine; _pageActivator = pageActivator; ViewStartPages = viewStartPages; RazorPage = razorPage; _htmlEncoder = htmlEncoder; + _diagnosticSource = diagnosticSource; } /// @@ -155,7 +165,13 @@ private async Task RenderPageAsync( private Task RenderPageCoreAsync(IRazorPage page, ViewContext context) { page.ViewContext = context; + + _diagnosticSource.BeforeRazorView(page, context); + _pageActivator.Activate(page, context); + + _diagnosticSource.AfterRazorView(page, context); + return page.ExecuteAsync(); } diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngine.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngine.cs index 243a899f46..de837275c9 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngine.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngine.cs @@ -44,6 +44,7 @@ public class RazorViewEngine : IRazorViewEngine private readonly ILogger _logger; private readonly RazorViewEngineOptions _options; private readonly RazorProject _razorProject; + private readonly DiagnosticSource _diagnosticSource; /// /// Initializes a new instance of the . @@ -54,7 +55,8 @@ public RazorViewEngine( HtmlEncoder htmlEncoder, IOptions optionsAccessor, RazorProject razorProject, - ILoggerFactory loggerFactory) + ILoggerFactory loggerFactory, + DiagnosticSource diagnosticSource) { _options = optionsAccessor.Value; @@ -77,6 +79,7 @@ public RazorViewEngine( _htmlEncoder = htmlEncoder; _logger = loggerFactory.CreateLogger(); _razorProject = razorProject; + _diagnosticSource = diagnosticSource; ViewLookupCache = new MemoryCache(new MemoryCacheOptions()); } @@ -466,7 +469,7 @@ private ViewEngineResult CreateViewEngineResult(ViewLocationCacheResult result, viewStarts[i] = viewStartItem.PageFactory(); } - var view = new RazorView(this, _pageActivator, viewStarts, page, _htmlEncoder); + var view = new RazorView(this, _pageActivator, viewStarts, page, _htmlEncoder, _diagnosticSource); return ViewEngineResult.Found(viewName, view); } diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs index d4c841332b..b8bbe7f4ec 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs @@ -19,6 +19,7 @@ public class PageResultExecutor : ViewExecutor { private readonly IRazorViewEngine _razorViewEngine; private readonly IRazorPageActivator _razorPageActivator; + private readonly DiagnosticSource _diagnosticSource; private readonly HtmlEncoder _htmlEncoder; /// @@ -42,6 +43,7 @@ public PageResultExecutor( _razorViewEngine = razorViewEngine; _htmlEncoder = htmlEncoder; _razorPageActivator = razorPageActivator; + _diagnosticSource = diagnosticSource; } /// @@ -76,7 +78,8 @@ public virtual Task ExecuteAsync(PageContext pageContext, PageResult result) _razorPageActivator, viewStarts, new RazorPageAdapter(result.Page), - _htmlEncoder); + _htmlEncoder, + _diagnosticSource); return ExecuteAsync(viewContext, result.ContentType, result.StatusCode); } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewEngineTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewEngineTest.cs index be2529dd93..54cec8e7a7 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewEngineTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewEngineTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Threading; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; @@ -1350,7 +1351,8 @@ public void CreateCacheResult_LogsPrecompiledViewFound() new HtmlTestEncoder(), GetOptionsAccessor(expanders: null), new FileProviderRazorProject(new TestFileProvider()), - loggerFactory); + loggerFactory, + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); // Act var result = viewEngine.CreateCacheResult(null, relativePath, false); @@ -1881,7 +1883,7 @@ public TestableRazorViewEngine( IRazorPageFactoryProvider pageFactory, IOptions optionsAccessor, RazorProject razorProject) - : base(pageFactory, Mock.Of(), new HtmlTestEncoder(), optionsAccessor, razorProject, NullLoggerFactory.Instance) + : base(pageFactory, Mock.Of(), new HtmlTestEncoder(), optionsAccessor, razorProject, NullLoggerFactory.Instance, new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")) { } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs index ce5dc500da..9184672f87 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -45,7 +46,8 @@ public async Task RenderAsync_AsPartial_BuffersOutput() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); var expected = viewContext.Writer; @@ -74,7 +76,8 @@ public async Task RenderAsync_AsPartial_ActivatesViews_WithThePassedInViewContex activator.Object, new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); var expectedWriter = viewContext.Writer; @@ -95,6 +98,51 @@ public async Task RenderAsync_AsPartial_ActivatesViews_WithThePassedInViewContex Assert.Same(expectedWriter, viewContext.Writer); } + [Fact] + public async Task RenderAsync_AsPartial_ActivatesViews_WritesBeforeAndAfterRazorViewEventDiagnostics() + { + // Arrange + var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()); + var page = new TestableRazorPageForDiagnostics(v => + { + // viewData is assigned to ViewContext by the activator + Assert.Same(viewData, v.ViewContext.ViewData); + }); + var activator = new Mock(); + + var adapter = new TestDiagnosticListener(); + var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor"); + diagnosticSource.SubscribeWithAdapter(adapter); + + var view = new RazorView( + Mock.Of(), + activator.Object, + new IRazorPage[0], + page, + new HtmlTestEncoder(), + diagnosticSource); + + var viewContext = CreateViewContext(view); + var expectedWriter = viewContext.Writer; + activator + .Setup(a => a.Activate(page, It.IsAny())) + .Callback((IRazorPage p, ViewContext c) => + { + Assert.Same(c, viewContext); + c.ViewData = viewData; + }) + .Verifiable(); + + // Act + await view.RenderAsync(viewContext); + + // Assert + Assert.NotNull(adapter.BeforeRazorView?.Page); + Assert.NotNull(adapter.BeforeRazorView?.ViewContext); + Assert.NotNull(adapter.AfterRazorView?.Page); + Assert.NotNull(adapter.AfterRazorView?.ViewContext); + } + [Fact] public async Task ViewContext_ExecutingPagePath_ReturnsPathOfRazorPageBeingExecuted() { @@ -143,7 +191,8 @@ public async Task ViewContext_ExecutingPagePath_ReturnsPathOfRazorPageBeingExecu activator, new[] { viewStart }, page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); var expectedWriter = viewContext.Writer; @@ -169,7 +218,8 @@ public async Task RenderAsync_AsPartial_ActivatesViews() activator.Object, new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -216,7 +266,8 @@ public async Task RenderAsync_AsPartial_ExecutesLayout_ButNotViewStartPages() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -240,7 +291,8 @@ public async Task RenderAsync_CreatesOutputBuffer() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); var original = viewContext.Writer; @@ -265,7 +317,8 @@ public async Task RenderAsync_CopiesBufferedContentToOutput() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); var original = viewContext.Writer; @@ -293,7 +346,8 @@ public async Task RenderAsync_ActivatesPages() activator.Object, new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -348,7 +402,8 @@ public async Task RenderAsync_ExecutesViewStart() activator.Object, new[] { viewStart1, viewStart2 }, page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -391,7 +446,8 @@ public async Task RenderAsync_ExecutesDefaultLayout() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var context = CreateViewContext(view); // Act @@ -444,7 +500,8 @@ public async Task RenderAsync_ExecutesDefaultLayout_WithViewStart() Mock.Of(), new[] { viewStart }, page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var context = CreateViewContext(view); // Act @@ -477,7 +534,8 @@ public async Task RenderAsync_ThrowsIfLayoutPageCannotBeFound_MessageUsesGetPage Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); viewEngine .Setup(v => v.GetPage(/*executingFilePath*/ null, layoutPath)) @@ -519,7 +577,8 @@ public async Task RenderAsync_ThrowsIfLayoutPageCannotBeFound_MessageUsesFindPag Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); viewEngine .Setup(v => v.GetPage(/*executingFilePath*/ null, layoutPath)) @@ -563,7 +622,8 @@ public async Task RenderAsync_ThrowsIfLayoutPageCannotBeFound_MessageUsesAllLoca Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); viewEngine .Setup(v => v.GetPage(/*executingFilePath*/ null, layoutPath)) @@ -638,7 +698,8 @@ public async Task RenderAsync_ExecutesLayoutPages() activator.Object, new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -678,7 +739,8 @@ public async Task RenderAsync_ThrowsIfSectionsWereDefinedButNotRendered() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act and Assert @@ -744,7 +806,8 @@ public async Task RenderAsync_SucceedsIfNestedSectionsAreRendered() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -812,7 +875,8 @@ public async Task RenderAsync_SucceedsIfRenderBodyIsNotInvoked_ButAllSectionsAre Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -874,7 +938,8 @@ public async Task RenderAsync_WithNestedSections_ThrowsIfSectionsWereDefinedButN Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act and Assert @@ -942,7 +1007,8 @@ public async Task RenderAsync_WithNestedSectionsOfTheSameName_ThrowsIfSectionsWe Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act and Assert @@ -976,7 +1042,8 @@ public async Task RenderAsync_ThrowsIfBodyWasNotRendered() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act and Assert @@ -1043,7 +1110,8 @@ public async Task RenderAsync_ExecutesNestedLayoutPages() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -1116,7 +1184,8 @@ public async Task RenderAsync_ExecutesNestedLayoutPages_WithRelativePaths() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -1156,7 +1225,8 @@ public async Task RenderAsync_Throws_IfLayoutPageReferencesSelf() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act and Assert @@ -1209,7 +1279,8 @@ public async Task RenderAsync_Throws_IfNestedLayoutPagesResultInCyclicReferences Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act and Assert @@ -1278,7 +1349,8 @@ public async Task RenderAsync_ExecutesNestedLayoutsWithNestedSections() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -1335,7 +1407,8 @@ public async Task RenderAsync_DoesNotCopyContentOnceRazorTextWriterIsNoLongerBuf Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -1389,7 +1462,8 @@ public async Task FlushAsync_DoesNotThrowWhenInvokedInsideOfASection() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -1419,7 +1493,8 @@ public async Task RenderAsync_ThrowsIfLayoutIsSpecifiedWhenNotBuffered() Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act and Assert @@ -1465,7 +1540,8 @@ public async Task RenderAsync_ThrowsIfFlushWasInvokedInsideRenderedSectionAndLay Mock.Of(), new IRazorPage[0], page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act and Assert @@ -1509,7 +1585,8 @@ public async Task RenderAsync_CopiesLayoutPropertyFromViewStart() Mock.Of(), new[] { viewStart1, viewStart2 }, page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -1566,7 +1643,8 @@ public async Task RenderAsync_CopiesLayoutPropertyFromViewStart_WithRelativePath Mock.Of(), new[] { viewStart1, viewStart2 }, page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -1610,7 +1688,8 @@ public async Task ResettingLayout_InViewStartCausesItToBeResetInPage() Mock.Of(), new[] { viewStart1, viewStart2 }, page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -1651,7 +1730,8 @@ public async Task RenderAsync_RendersViewStartsInOrderInWhichTheyAreSpecified() Mock.Of(), new[] { viewStart1, viewStart2 }, page, - new HtmlTestEncoder()); + new HtmlTestEncoder(), + new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor")); var viewContext = CreateViewContext(view); // Act @@ -1678,6 +1758,28 @@ private static ViewContext CreateViewContext(RazorView view) new HtmlHelperOptions()); } + public class TestableRazorPageForDiagnostics : RazorPage + { + private readonly Action _executeAction; + + public TestableRazorPageForDiagnostics(Action executeAction) + { + _executeAction = executeAction; + HtmlEncoder = new HtmlTestEncoder(); + } + + public void RenderBodyPublic() + { + Write(RenderBody()); + } + + public override Task ExecuteAsync() + { + _executeAction(this); + return Task.FromResult(0); + } + } + private class TestableRazorPage : RazorPage { private readonly Action _executeAction; diff --git a/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/IProxyPage.cs b/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/IProxyPage.cs new file mode 100644 index 0000000000..c39cd01d8b --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/IProxyPage.cs @@ -0,0 +1,9 @@ +// 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. + +namespace Microsoft.AspNetCore.Mvc +{ + public interface IProxyPage + { + } +} diff --git a/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs b/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs index dc1c0b2859..8fe0413082 100644 --- a/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs +++ b/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs @@ -221,6 +221,42 @@ public virtual void OnAfterView(IProxyView view, IProxyViewContext viewContext) }; } + public class OnBeforeRazorViewEventData + { + public IProxyPage Page { get; set; } + public IProxyViewContext ViewContext { get; set; } + } + + public OnBeforeRazorViewEventData BeforeRazorView { get; set; } + + [DiagnosticName("Microsoft.AspNetCore.Mvc.Razor.BeforeRazorView")] + public virtual void OnBeforeRazorView(IProxyPage page, IProxyViewContext viewContext) + { + BeforeRazorView = new OnBeforeRazorViewEventData() + { + Page = page, + ViewContext = viewContext, + }; + } + + public class OnAfterRazorViewEventData + { + public IProxyPage Page { get; set; } + public IProxyViewContext ViewContext { get; set; } + } + + public OnAfterRazorViewEventData AfterRazorView { get; set; } + + [DiagnosticName("Microsoft.AspNetCore.Mvc.Razor.AfterRazorView")] + public virtual void OnAfterRazorView(IProxyPage page, IProxyViewContext viewContext) + { + AfterRazorView = new OnAfterRazorViewEventData() + { + Page = page, + ViewContext = viewContext, + }; + } + public class OnBeforeViewComponentEventData { public IProxyActionDescriptor ActionDescriptor { get; set; } From 6bc17c513432c1dad7a6108616c26e376426a980 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Mon, 26 Jun 2017 10:28:44 -0700 Subject: [PATCH 2/4] PR feedback addressed On branch jbagga/DiagnosticsPartialViews6222 --- .../MvcRazorDiagnosticSourceExtensions.cs | 20 +++++++++++++++---- .../RazorView.cs | 15 +++++++++----- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs index 917962838a..c324e509e7 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal { public static class MvcRazorDiagnosticSourceExtensions { - public static void BeforeRazorView( + public static void BeforeRazorPage( this DiagnosticSource diagnosticSource, IRazorPage page, ViewContext viewContext) @@ -17,11 +17,17 @@ public static void BeforeRazorView( { diagnosticSource.Write( "Microsoft.AspNetCore.Mvc.Razor.BeforeRazorView", - new { page = page, viewContext = viewContext, }); + new + { + page = page, + viewContext = viewContext, + actionDescriptor = viewContext.ActionDescriptor, + httpContext = viewContext.HttpContext, + }); } } - public static void AfterRazorView( + public static void AfterRazorPage( this DiagnosticSource diagnosticSource, IRazorPage page, ViewContext viewContext) @@ -30,7 +36,13 @@ public static void AfterRazorView( { diagnosticSource.Write( "Microsoft.AspNetCore.Mvc.Razor.AfterRazorView", - new { page = page, viewContext = viewContext, }); + new + { + page = page, + viewContext = viewContext, + actionDescriptor = viewContext.ActionDescriptor, + httpContext = viewContext.HttpContext, + }); } } } diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs index 63aab535a2..91f66db9bb 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs @@ -165,14 +165,19 @@ private async Task RenderPageAsync( private Task RenderPageCoreAsync(IRazorPage page, ViewContext context) { page.ViewContext = context; - - _diagnosticSource.BeforeRazorView(page, context); - _pageActivator.Activate(page, context); - _diagnosticSource.AfterRazorView(page, context); + _diagnosticSource.BeforeRazorPage(page, context); - return page.ExecuteAsync(); + try + { + return page.ExecuteAsync(); + } + + finally + { + _diagnosticSource.AfterRazorPage(page, context); + } } private async Task RenderViewStartsAsync(ViewContext context) From 7a5d700407745baec975b9ec1f7ae1a408a213c3 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Mon, 26 Jun 2017 11:42:54 -0700 Subject: [PATCH 3/4] Renaming --- .../RazorViewTest.cs | 12 ++++--- .../TestDiagnosticListener.cs | 32 ++++++++++++++----- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs index 9184672f87..d7aa6f464d 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs @@ -137,10 +137,14 @@ public async Task RenderAsync_AsPartial_ActivatesViews_WritesBeforeAndAfterRazor await view.RenderAsync(viewContext); // Assert - Assert.NotNull(adapter.BeforeRazorView?.Page); - Assert.NotNull(adapter.BeforeRazorView?.ViewContext); - Assert.NotNull(adapter.AfterRazorView?.Page); - Assert.NotNull(adapter.AfterRazorView?.ViewContext); + Assert.NotNull(adapter.BeforeRazorPage?.Page); + Assert.NotNull(adapter.BeforeRazorPage?.ViewContext); + Assert.NotNull(adapter.BeforeRazorPage?.ActionDescriptor); + Assert.NotNull(adapter.BeforeRazorPage?.HttpContext); + Assert.NotNull(adapter.AfterRazorPage?.Page); + Assert.NotNull(adapter.AfterRazorPage?.ViewContext); + Assert.NotNull(adapter.AfterRazorPage?.ActionDescriptor); + Assert.NotNull(adapter.AfterRazorPage?.HttpContext); } [Fact] diff --git a/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs b/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs index 8fe0413082..d68e52cd42 100644 --- a/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs +++ b/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs @@ -221,39 +221,55 @@ public virtual void OnAfterView(IProxyView view, IProxyViewContext viewContext) }; } - public class OnBeforeRazorViewEventData + public class OnBeforeRazorPageEventData { public IProxyPage Page { get; set; } public IProxyViewContext ViewContext { get; set; } + public IProxyActionDescriptor ActionDescriptor { get; set; } + public IProxyHttpContext HttpContext { get; set; } } - public OnBeforeRazorViewEventData BeforeRazorView { get; set; } + public OnBeforeRazorPageEventData BeforeRazorPage { get; set; } [DiagnosticName("Microsoft.AspNetCore.Mvc.Razor.BeforeRazorView")] - public virtual void OnBeforeRazorView(IProxyPage page, IProxyViewContext viewContext) + public virtual void OnBeforeRazorPage( + IProxyPage page, + IProxyViewContext viewContext, + IProxyActionDescriptor actionDescriptor, + IProxyHttpContext httpContext) { - BeforeRazorView = new OnBeforeRazorViewEventData() + BeforeRazorPage = new OnBeforeRazorPageEventData() { Page = page, ViewContext = viewContext, + ActionDescriptor = actionDescriptor, + HttpContext = httpContext, }; } - public class OnAfterRazorViewEventData + public class OnAfterRazorPageEventData { public IProxyPage Page { get; set; } public IProxyViewContext ViewContext { get; set; } + public IProxyActionDescriptor ActionDescriptor { get; set; } + public IProxyHttpContext HttpContext { get; set; } } - public OnAfterRazorViewEventData AfterRazorView { get; set; } + public OnAfterRazorPageEventData AfterRazorPage { get; set; } [DiagnosticName("Microsoft.AspNetCore.Mvc.Razor.AfterRazorView")] - public virtual void OnAfterRazorView(IProxyPage page, IProxyViewContext viewContext) + public virtual void OnAfterRazorPage( + IProxyPage page, + IProxyViewContext viewContext, + IProxyActionDescriptor actionDescriptor, + IProxyHttpContext httpContext) { - AfterRazorView = new OnAfterRazorViewEventData() + AfterRazorPage = new OnAfterRazorPageEventData() { Page = page, ViewContext = viewContext, + ActionDescriptor = actionDescriptor, + HttpContext = httpContext, }; } From 7e121724ac0e9319c83293a16ef0b39a604dc0cf Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Mon, 26 Jun 2017 14:26:09 -0700 Subject: [PATCH 4/4] Change event name --- .../MvcRazorDiagnosticSourceExtensions.cs | 12 +++++------ .../RazorView.cs | 9 ++++----- .../RazorViewTest.cs | 16 +++++++-------- .../TestDiagnosticListener.cs | 20 +++++++++---------- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs index c324e509e7..a60f5fb587 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/MvcRazorDiagnosticSourceExtensions.cs @@ -8,15 +8,15 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal { public static class MvcRazorDiagnosticSourceExtensions { - public static void BeforeRazorPage( + public static void BeforeViewPage( this DiagnosticSource diagnosticSource, IRazorPage page, ViewContext viewContext) { - if (diagnosticSource.IsEnabled("Microsoft.AspNetCore.Mvc.Razor.BeforeRazorView")) + if (diagnosticSource.IsEnabled("Microsoft.AspNetCore.Mvc.Razor.BeforeViewPage")) { diagnosticSource.Write( - "Microsoft.AspNetCore.Mvc.Razor.BeforeRazorView", + "Microsoft.AspNetCore.Mvc.Razor.BeforeViewPage", new { page = page, @@ -27,15 +27,15 @@ public static void BeforeRazorPage( } } - public static void AfterRazorPage( + public static void AfterViewPage( this DiagnosticSource diagnosticSource, IRazorPage page, ViewContext viewContext) { - if (diagnosticSource.IsEnabled("Microsoft.AspNetCore.Mvc.Razor.AfterRazorView")) + if (diagnosticSource.IsEnabled("Microsoft.AspNetCore.Mvc.Razor.AfterViewPage")) { diagnosticSource.Write( - "Microsoft.AspNetCore.Mvc.Razor.AfterRazorView", + "Microsoft.AspNetCore.Mvc.Razor.AfterViewPage", new { page = page, diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs index 91f66db9bb..240c80681c 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorView.cs @@ -162,21 +162,20 @@ private async Task RenderPageAsync( } } - private Task RenderPageCoreAsync(IRazorPage page, ViewContext context) + private async Task RenderPageCoreAsync(IRazorPage page, ViewContext context) { page.ViewContext = context; _pageActivator.Activate(page, context); - _diagnosticSource.BeforeRazorPage(page, context); + _diagnosticSource.BeforeViewPage(page, context); try { - return page.ExecuteAsync(); + await page.ExecuteAsync(); } - finally { - _diagnosticSource.AfterRazorPage(page, context); + _diagnosticSource.AfterViewPage(page, context); } } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs index d7aa6f464d..a7ca3fc77e 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/RazorViewTest.cs @@ -137,14 +137,14 @@ public async Task RenderAsync_AsPartial_ActivatesViews_WritesBeforeAndAfterRazor await view.RenderAsync(viewContext); // Assert - Assert.NotNull(adapter.BeforeRazorPage?.Page); - Assert.NotNull(adapter.BeforeRazorPage?.ViewContext); - Assert.NotNull(adapter.BeforeRazorPage?.ActionDescriptor); - Assert.NotNull(adapter.BeforeRazorPage?.HttpContext); - Assert.NotNull(adapter.AfterRazorPage?.Page); - Assert.NotNull(adapter.AfterRazorPage?.ViewContext); - Assert.NotNull(adapter.AfterRazorPage?.ActionDescriptor); - Assert.NotNull(adapter.AfterRazorPage?.HttpContext); + Assert.NotNull(adapter.BeforeViewPage?.Page); + Assert.NotNull(adapter.BeforeViewPage?.ViewContext); + Assert.NotNull(adapter.BeforeViewPage?.ActionDescriptor); + Assert.NotNull(adapter.BeforeViewPage?.HttpContext); + Assert.NotNull(adapter.AfterViewPage?.Page); + Assert.NotNull(adapter.AfterViewPage?.ViewContext); + Assert.NotNull(adapter.AfterViewPage?.ActionDescriptor); + Assert.NotNull(adapter.AfterViewPage?.HttpContext); } [Fact] diff --git a/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs b/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs index d68e52cd42..02966a1ece 100644 --- a/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs +++ b/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/TestDiagnosticListener.cs @@ -221,7 +221,7 @@ public virtual void OnAfterView(IProxyView view, IProxyViewContext viewContext) }; } - public class OnBeforeRazorPageEventData + public class OnBeforeViewPageEventData { public IProxyPage Page { get; set; } public IProxyViewContext ViewContext { get; set; } @@ -229,16 +229,16 @@ public class OnBeforeRazorPageEventData public IProxyHttpContext HttpContext { get; set; } } - public OnBeforeRazorPageEventData BeforeRazorPage { get; set; } + public OnBeforeViewPageEventData BeforeViewPage { get; set; } - [DiagnosticName("Microsoft.AspNetCore.Mvc.Razor.BeforeRazorView")] - public virtual void OnBeforeRazorPage( + [DiagnosticName("Microsoft.AspNetCore.Mvc.Razor.BeforeViewPage")] + public virtual void OnBeforeViewPage( IProxyPage page, IProxyViewContext viewContext, IProxyActionDescriptor actionDescriptor, IProxyHttpContext httpContext) { - BeforeRazorPage = new OnBeforeRazorPageEventData() + BeforeViewPage = new OnBeforeViewPageEventData() { Page = page, ViewContext = viewContext, @@ -247,7 +247,7 @@ public virtual void OnBeforeRazorPage( }; } - public class OnAfterRazorPageEventData + public class OnAfterViewPageEventData { public IProxyPage Page { get; set; } public IProxyViewContext ViewContext { get; set; } @@ -255,16 +255,16 @@ public class OnAfterRazorPageEventData public IProxyHttpContext HttpContext { get; set; } } - public OnAfterRazorPageEventData AfterRazorPage { get; set; } + public OnAfterViewPageEventData AfterViewPage { get; set; } - [DiagnosticName("Microsoft.AspNetCore.Mvc.Razor.AfterRazorView")] - public virtual void OnAfterRazorPage( + [DiagnosticName("Microsoft.AspNetCore.Mvc.Razor.AfterViewPage")] + public virtual void OnAfterViewPage( IProxyPage page, IProxyViewContext viewContext, IProxyActionDescriptor actionDescriptor, IProxyHttpContext httpContext) { - AfterRazorPage = new OnAfterRazorPageEventData() + AfterViewPage = new OnAfterViewPageEventData() { Page = page, ViewContext = viewContext,