Removing PageInstrumentation

Fixes #3497
This commit is contained in:
Pranav K 2015-11-20 15:11:49 -08:00
parent 5ef14e95b7
commit 79d517483b
24 changed files with 93 additions and 645 deletions

View File

@ -28,6 +28,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FAD65E9C-3CF3-4F68-9757-C7358604030B}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
NuGetPackageVerifier.json = NuGetPackageVerifier.json
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.WebApiCompatShim", "src\Microsoft.AspNet.Mvc.WebApiCompatShim\Microsoft.AspNet.Mvc.WebApiCompatShim.xproj", "{23D30B8C-04B1-4577-A604-ED27EA1E4A0E}"
@ -42,8 +43,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TagHelperSample.Web", "samp
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.TagHelpers.Test", "test\Microsoft.AspNet.Mvc.TagHelpers.Test\Microsoft.AspNet.Mvc.TagHelpers.Test.xproj", "{860119ED-3DB1-424D-8D0A-30132A8A7D96}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.PageExecutionInstrumentation.Interfaces", "src\Microsoft.AspNet.PageExecutionInstrumentation.Interfaces\Microsoft.AspNet.PageExecutionInstrumentation.Interfaces.xproj", "{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.TestCommon", "test\Microsoft.AspNet.Mvc.TestCommon\Microsoft.AspNet.Mvc.TestCommon.xproj", "{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.IntegrationTests", "test\Microsoft.AspNet.Mvc.IntegrationTests\Microsoft.AspNet.Mvc.IntegrationTests.xproj", "{864FA09D-1E48-403A-A6C8-4F079D2A30F0}"
@ -244,18 +243,6 @@ Global
{860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|x86.ActiveCfg = Release|Any CPU
{860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|x86.Build.0 = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|x86.ActiveCfg = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|x86.Build.0 = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|Any CPU.Build.0 = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|x86.ActiveCfg = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|x86.Build.0 = Release|Any CPU
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|x86.ActiveCfg = Debug|Any CPU
@ -525,7 +512,6 @@ Global
{B2347320-308E-4D2B-AEC8-005DFA68B0C9} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{2223120F-D675-40DA-8CD8-11DC14A0B2C7} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
{860119ED-3DB1-424D-8D0A-30132A8A7D96} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{864FA09D-1E48-403A-A6C8-4F079D2A30F0} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{1154203C-7579-4525-906E-BC55268421C1} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}

17
Mvc.sln
View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
VisualStudioVersion = 14.0.24711.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
EndProject
@ -116,8 +116,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ControllersFromServicesWebS
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ControllersFromServicesClassLibrary", "test\WebSites\ControllersFromServicesClassLibrary\ControllersFromServicesClassLibrary.xproj", "{551DC89E-2A13-4CF2-83D7-1ADD802443D5}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.PageExecutionInstrumentation.Interfaces", "src\Microsoft.AspNet.PageExecutionInstrumentation.Interfaces\Microsoft.AspNet.PageExecutionInstrumentation.Interfaces.xproj", "{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "UserClassLibrary", "test\WebSites\UserClassLibrary\UserClassLibrary.xproj", "{C651F432-4EBE-41A6-BAD2-3E07CCBA209C}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ControllerDiscoveryConventionsWebSite", "test\WebSites\ControllerDiscoveryConventionsWebSite\ControllerDiscoveryConventionsWebSite.xproj", "{A19022EF-9BA3-4349-94E4-F48E13E1C8AE}"
@ -720,18 +718,6 @@ Global
{551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Release|x86.ActiveCfg = Release|Any CPU
{551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Release|x86.Build.0 = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|x86.ActiveCfg = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Debug|x86.Build.0 = Debug|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|Any CPU.Build.0 = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|x86.ActiveCfg = Release|Any CPU
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE}.Release|x86.Build.0 = Release|Any CPU
{C651F432-4EBE-41A6-BAD2-3E07CCBA209C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C651F432-4EBE-41A6-BAD2-3E07CCBA209C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C651F432-4EBE-41A6-BAD2-3E07CCBA209C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -1159,7 +1145,6 @@ Global
{AC9BE567-540E-4C70-90C2-AAF021307A80} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{983741B2-4424-4ED1-9B03-7675A67230C8} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{551DC89E-2A13-4CF2-83D7-1ADD802443D5} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{4DA2D7C1-A7B6-4C01-B57D-89E6EA4609DE} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{C651F432-4EBE-41A6-BAD2-3E07CCBA209C} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{A19022EF-9BA3-4349-94E4-F48E13E1C8AE} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{B11C99C9-E577-4CA2-AC53-4F20EA71AD34} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}

View File

@ -22,8 +22,7 @@
"Microsoft.AspNet.Mvc.Razor.Host": { },
"Microsoft.AspNet.Mvc.TagHelpers": { },
"Microsoft.AspNet.Mvc.ViewFeatures": { },
"Microsoft.AspNet.Mvc.WebApiCompatShim": { },
"Microsoft.AspNet.PageExecutionInstrumentation.Interfaces": { }
"Microsoft.AspNet.Mvc.WebApiCompatShim": { }
}
},
"Default": { // Rules to run for packages not listed in any other set.

View File

@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.PageExecutionInstrumentation;
namespace Microsoft.AspNet.Mvc.Razor
{
@ -45,11 +44,6 @@ namespace Microsoft.AspNet.Mvc.Razor
/// </summary>
string Layout { get; set; }
/// <summary>
/// Gets or sets a <see cref="IPageExecutionContext"/> instance used to instrument the page execution.
/// </summary>
IPageExecutionContext PageExecutionContext { get; set; }
/// <summary>
/// Gets or sets the sections that can be rendered by this page.
/// </summary>

View File

@ -16,7 +16,6 @@ using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.AspNet.Mvc.Razor.Internal;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.AspNet.PageExecutionInstrumentation;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Extensions.DependencyInjection;
@ -77,9 +76,6 @@ namespace Microsoft.AspNet.Mvc.Razor
[RazorInject]
public HtmlEncoder HtmlEncoder { get; set; }
/// <inheritdoc />
public IPageExecutionContext PageExecutionContext { get; set; }
/// <summary>
/// Gets or sets a <see cref="DiagnosticSource.DiagnosticSource"/> instance used to instrument the page execution.
/// </summary>
@ -937,7 +933,6 @@ namespace Microsoft.AspNet.Mvc.Razor
{
const string BeginContextEvent = "Microsoft.AspNet.Mvc.Razor.BeginInstrumentationContext";
PageExecutionContext?.BeginContext(position, length, isLiteral);
if (DiagnosticSource?.IsEnabled(BeginContextEvent) == true)
{
DiagnosticSource.Write(
@ -957,7 +952,6 @@ namespace Microsoft.AspNet.Mvc.Razor
{
const string EndContextEvent = "Microsoft.AspNet.Mvc.Razor.EndInstrumentationContext";
PageExecutionContext?.EndContext();
if (DiagnosticSource?.IsEnabled(EndContextEvent) == true)
{
DiagnosticSource.Write(

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Mvc.Razor
/// This type is designed to avoid creating large in-memory strings when buffering and supporting the contract that
/// <see cref="RazorPage.FlushAsync"/> expects.
/// </remarks>
public class RazorTextWriter : HtmlTextWriter, IBufferedTextWriter
public class RazorTextWriter : HtmlTextWriter
{
/// <summary>
/// Creates a new instance of <see cref="RazorTextWriter"/>.
@ -228,8 +228,9 @@ namespace Microsoft.AspNet.Mvc.Razor
var targetRazorTextWriter = writer as RazorTextWriter;
if (targetRazorTextWriter != null)
{
writer = targetRazorTextWriter.IsBuffering ? targetRazorTextWriter.BufferedWriter :
targetRazorTextWriter.UnbufferedWriter;
writer = targetRazorTextWriter.IsBuffering ?
targetRazorTextWriter.BufferedWriter :
targetRazorTextWriter.UnbufferedWriter;
}
return writer;

View File

@ -3,14 +3,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.PageExecutionInstrumentation;
namespace Microsoft.AspNet.Mvc.Razor
{
@ -23,7 +20,6 @@ namespace Microsoft.AspNet.Mvc.Razor
private readonly IRazorViewEngine _viewEngine;
private readonly IRazorPageActivator _pageActivator;
private readonly HtmlEncoder _htmlEncoder;
private IPageExecutionListenerFeature _pageExecutionFeature;
/// <summary>
/// Initializes a new instance of <see cref="RazorView"/>
@ -89,11 +85,6 @@ namespace Microsoft.AspNet.Mvc.Razor
/// </summary>
public IReadOnlyList<IRazorPage> ViewStartPages { get; }
private bool EnableInstrumentation
{
get { return _pageExecutionFeature != null; }
}
/// <inheritdoc />
public virtual async Task RenderAsync(ViewContext context)
{
@ -102,40 +93,22 @@ namespace Microsoft.AspNet.Mvc.Razor
throw new ArgumentNullException(nameof(context));
}
_pageExecutionFeature = context.HttpContext.Features.Get<IPageExecutionListenerFeature>();
var bodyWriter = await RenderPageAsync(RazorPage, context, ViewStartPages);
await RenderLayoutAsync(context, bodyWriter);
}
private async Task<IBufferedTextWriter> RenderPageAsync(
private async Task<RazorTextWriter> RenderPageAsync(
IRazorPage page,
ViewContext context,
IReadOnlyList<IRazorPage> viewStartPages)
{
var razorTextWriter = new RazorTextWriter(context.Writer, context.Writer.Encoding, _htmlEncoder);
var writer = (TextWriter)razorTextWriter;
var bufferedWriter = (IBufferedTextWriter)razorTextWriter;
if (EnableInstrumentation)
{
writer = _pageExecutionFeature.DecorateWriter(razorTextWriter);
bufferedWriter = writer as IBufferedTextWriter;
if (bufferedWriter == null)
{
var message = Resources.FormatInstrumentation_WriterMustBeBufferedTextWriter(
nameof(TextWriter),
_pageExecutionFeature.GetType().FullName,
typeof(IBufferedTextWriter).FullName);
throw new InvalidOperationException(message);
}
}
// The writer for the body is passed through the ViewContext, allowing things like HtmlHelpers
// and ViewComponents to reference it.
var oldWriter = context.Writer;
var oldFilePath = context.ExecutingFilePath;
context.Writer = writer;
context.Writer = razorTextWriter;
context.ExecutingFilePath = page.Path;
try
@ -147,24 +120,19 @@ namespace Microsoft.AspNet.Mvc.Razor
}
await RenderPageCoreAsync(page, context);
return bufferedWriter;
return razorTextWriter;
}
finally
{
context.Writer = oldWriter;
context.ExecutingFilePath = oldFilePath;
writer.Dispose();
razorTextWriter.Dispose();
}
}
private Task RenderPageCoreAsync(IRazorPage page, ViewContext context)
{
page.ViewContext = context;
if (EnableInstrumentation)
{
page.PageExecutionContext = _pageExecutionFeature.GetContext(page.Path, context.Writer);
}
_pageActivator.Activate(page, context);
return page.ExecuteAsync();
}
@ -201,7 +169,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private async Task RenderLayoutAsync(
ViewContext context,
IBufferedTextWriter bodyWriter)
RazorTextWriter bodyWriter)
{
// A layout page can specify another layout page. We'll need to continue
// looking for layout pages until they're no longer specified.

View File

@ -13,7 +13,6 @@
"Microsoft.AspNet.Mvc.Razor.Host": "6.0.0-*",
"Microsoft.AspNet.Mvc.ViewFeatures": "6.0.0-*",
"Microsoft.AspNet.Razor.Runtime.Precompilation": "4.0.0-*",
"Microsoft.AspNet.PageExecutionInstrumentation.Interfaces": "1.0.0-*",
"Microsoft.Extensions.HashCodeCombiner.Sources": {
"version": "1.0.0-*",
"type": "build"

View File

@ -1,32 +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.IO;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.Razor
{
/// <summary>
/// Specifies the contracts for a <see cref="TextWriter"/> that buffers its content.
/// </summary>
public interface IBufferedTextWriter
{
/// <summary>
/// Gets a flag that determines if content is currently being buffered.
/// </summary>
bool IsBuffering { get; }
/// <summary>
/// Copies the buffered content to the <paramref name="writer"/>.
/// </summary>
/// <param name="writer">The <see cref="TextWriter"/> to copy the contents to.</param>
void CopyTo(TextWriter writer);
/// <summary>
/// Asynchronously copies the buffered content to the <paramref name="writer"/>.
/// </summary>
/// <param name="writer">The <see cref="TextWriter"/> to copy the contents to.</param>
/// <returns>A <see cref="Task"/> representing the copy operation.</returns>
Task CopyToAsync(TextWriter writer);
}
}

View File

@ -1,25 +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.
namespace Microsoft.AspNet.PageExecutionInstrumentation
{
/// <summary>
/// Specifies the contracts for a execution context that instruments web page execution.
/// </summary>
public interface IPageExecutionContext
{
/// <summary>
/// Invoked at the start of a write operation.
/// </summary>
/// <param name="position">The absolute character position of the expression or text in the Razor file.</param>
/// <param name="length">The character length of the expression or text in the Razor file.</param>
/// <param name="isLiteral">A flag that indicates if the operation is for a literal text and not for a
/// language expression.</param>
void BeginContext(int position, int length, bool isLiteral);
/// <summary>
/// Invoked at the end of a write operation.
/// </summary>
void EndContext();
}
}

View File

@ -1,30 +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.IO;
namespace Microsoft.AspNet.PageExecutionInstrumentation
{
/// <summary>
/// Specifies the contracts for a HTTP feature that provides the context to instrument a web page.
/// </summary>
public interface IPageExecutionListenerFeature
{
/// <summary>
/// Decorates the <see cref="TextWriter"/> used by web page instances to
/// write the result to.
/// </summary>
/// <param name="writer">The output <see cref="TextWriter"/> for the web page.</param>
/// <returns>A <see cref="TextWriter"/> that wraps <paramref name="writer"/>.</returns>
TextWriter DecorateWriter(TextWriter writer);
/// <summary>
/// Creates a <see cref="IPageExecutionContext"/> for the specified <paramref name="sourceFilePath"/>.
/// </summary>
/// <param name="sourceFilePath">The path of the page.</param>
/// <param name="writer">The <see cref="TextWriter"/> obtained from <see cref="DecorateWriter(TextWriter)"/>.
/// </param>
/// <returns>The <see cref="IPageExecutionContext"/>.</returns>
IPageExecutionContext GetContext(string sourceFilePath, TextWriter writer);
}
}

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>4da2d7c1-a7b6-4c01-b57d-89e6ea4609de</ProjectGuid>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -1,8 +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.Reflection;
using System.Resources;
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: NeutralResourcesLanguage("en-us")]

View File

@ -1,21 +0,0 @@
{
"description": "Abstractions for page instrumentation.",
"version": "1.0.0-*",
"repository": {
"type": "git",
"url": "git://github.com/aspnet/mvc"
},
"compilationOptions": {
"warningsAsErrors": true,
"keyFile": "../../tools/Key.snk"
},
"frameworks": {
"net451": {},
"dotnet5.4": {
"dependencies": {
"System.IO": "4.0.11-*",
"System.Resources.ResourceManager": "4.0.1-*"
}
}
}
}

View File

@ -1,27 +1,20 @@
<div>
2147483647
viewstart-content
view-with-partial-content
<p class="class">partial-content</p>
<p class="class">partial-content</p>
</div>
<p>/Views/_ViewStart.cshtml: Non-literal at 96 contains 16 characters.</p>
<p>/Views/_ViewStart.cshtml: Literal at 112 contains 2 characters.</p>
<p>/Views/Home/ViewWithPartial.cshtml: Literal at 0 contains 27 characters.</p>
<p>/Views/Home/ViewWithPartial.cshtml: Non-literal at 28 contains 39 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Literal at 31 contains 2 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Literal at 33 contains 8 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Non-literal at 41 contains 4 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Literal at 45 contains 1 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Literal at 46 contains 20 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Literal at 67 contains 2 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Literal at 31 contains 2 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Literal at 33 contains 8 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Non-literal at 41 contains 4 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Literal at 45 contains 1 characters.</p>
<p>/Views/Home/_PartialView.cshtml: Literal at 46 contains 20 characters.</p>
<p>/Views/_Layout.cshtml: Literal at 82 contains 7 characters.</p>
<p>/Views/_Layout.cshtml: Non-literal at 90 contains 12 characters.</p>
<p>/Views/_Layout.cshtml: Literal at 102 contains 2 characters.</p>
<p>/Views/_Layout.cshtml: Non-literal at 105 contains 12 characters.</p>
<p>/Views/_Layout.cshtml: Literal at 117 contains 10 characters.</p>
/Views/_ViewStart.cshtml: Non-literal at 96 contains 16 characters.
/Views/_ViewStart.cshtml: Literal at 112 contains 2 characters.
/Views/Home/ViewWithPartial.cshtml: Literal at 0 contains 27 characters.
/Views/Home/ViewWithPartial.cshtml: Non-literal at 28 contains 39 characters.
/Views/Home/_PartialView.cshtml: Literal at 31 contains 2 characters.
/Views/Home/_PartialView.cshtml: Literal at 33 contains 8 characters.
/Views/Home/_PartialView.cshtml: Non-literal at 41 contains 4 characters.
/Views/Home/_PartialView.cshtml: Literal at 45 contains 1 characters.
/Views/Home/_PartialView.cshtml: Literal at 46 contains 20 characters.
/Views/Home/ViewWithPartial.cshtml: Literal at 67 contains 2 characters.
/Views/Home/_PartialView.cshtml: Literal at 31 contains 2 characters.
/Views/Home/_PartialView.cshtml: Literal at 33 contains 8 characters.
/Views/Home/_PartialView.cshtml: Non-literal at 41 contains 4 characters.
/Views/Home/_PartialView.cshtml: Literal at 45 contains 1 characters.
/Views/Home/_PartialView.cshtml: Literal at 46 contains 20 characters.
/Views/_Layout.cshtml: Literal at 0 contains 7 characters.
/Views/_Layout.cshtml: Non-literal at 8 contains 12 characters.
/Views/_Layout.cshtml: Literal at 20 contains 2 characters.
/Views/_Layout.cshtml: Non-literal at 23 contains 12 characters.
/Views/_Layout.cshtml: Literal at 35 contains 10 characters.

View File

@ -15,7 +15,6 @@ using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.AspNet.PageExecutionInstrumentation;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.AspNet.Routing;
@ -659,93 +658,6 @@ namespace Microsoft.AspNet.Mvc.Razor
Assert.Same(HtmlString.Empty, actual);
}
[Fact]
public async Task WriteAttribute_CallsBeginAndEndContext_OnPageExecutionContext()
{
// Arrange
var page = CreatePage(p =>
{
p.HtmlEncoder = new HtmlTestEncoder();
p.BeginWriteAttribute("href", "prefix", 0, "suffix", 34, 2);
p.WriteAttributeValue("prefix", 0, "attr1-value", 8, 14, true);
p.WriteAttributeValue("prefix2", 22, "attr2", 29, 5, false);
p.EndWriteAttribute();
});
var context = new Mock<IPageExecutionContext>(MockBehavior.Strict);
var sequence = new MockSequence();
context.InSequence(sequence).Setup(f => f.BeginContext(0, 6, true)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
context.InSequence(sequence).Setup(f => f.BeginContext(0, 6, true)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
context.InSequence(sequence).Setup(f => f.BeginContext(8, 14, true)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
context.InSequence(sequence).Setup(f => f.BeginContext(22, 7, true)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
context.InSequence(sequence).Setup(f => f.BeginContext(29, 5, false)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
context.InSequence(sequence).Setup(f => f.BeginContext(34, 6, true)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
page.PageExecutionContext = context.Object;
// Act
await page.ExecuteAsync();
// Assert
context.Verify();
}
[Fact]
public async Task WriteAttribute_WithBoolValue_CallsBeginAndEndContext_OnPageExecutionContext()
{
// Arrange
var page = CreatePage(p =>
{
p.HtmlEncoder = new HtmlTestEncoder();
p.BeginWriteAttribute("href", "prefix", 0, "suffix", 10, 1);
p.WriteAttributeValue("", 6, "true", 6, 4, false);
p.EndWriteAttribute();
});
var context = new Mock<IPageExecutionContext>(MockBehavior.Strict);
var sequence = new MockSequence();
context.InSequence(sequence).Setup(f => f.BeginContext(0, 6, true)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
context.InSequence(sequence).Setup(f => f.BeginContext(6, 4, false)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
context.InSequence(sequence).Setup(f => f.BeginContext(10, 6, true)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
page.PageExecutionContext = context.Object;
// Act
await page.ExecuteAsync();
// Assert
context.Verify();
}
[Fact]
public async Task WriteAttribute_CallsBeginAndEndContext_OnPrefixAndSuffixValues()
{
// Arrange
var page = CreatePage(p =>
{
p.BeginWriteAttribute("href", "prefix", 0, "tail", 7, 0);
p.EndWriteAttribute();
});
var context = new Mock<IPageExecutionContext>(MockBehavior.Strict);
var sequence = new MockSequence();
context.InSequence(sequence).Setup(f => f.BeginContext(0, 6, true)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
context.InSequence(sequence).Setup(f => f.BeginContext(7, 4, true)).Verifiable();
context.InSequence(sequence).Setup(f => f.EndContext()).Verifiable();
page.PageExecutionContext = context.Object;
// Act
await page.ExecuteAsync();
// Assert
context.Verify();
}
[Fact]
public async Task WriteAttribute_WritesBeginAndEndEvents_ToDiagnosticSource()
{

View File

@ -12,7 +12,6 @@ using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.AspNet.PageExecutionInstrumentation;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.Primitives;
using Microsoft.Extensions.WebEncoders.Testing;
@ -54,7 +53,7 @@ namespace Microsoft.AspNet.Mvc.Razor
// Assert
Assert.NotSame(expected, actual);
Assert.IsAssignableFrom<IBufferedTextWriter>(actual);
Assert.IsType<RazorTextWriter>(actual);
Assert.Equal("HtmlEncode[[Hello world]]", viewContext.Writer.ToString());
}
@ -1373,163 +1372,6 @@ namespace Microsoft.AspNet.Mvc.Razor
Assert.Equal(expected, ex.Message);
}
[Fact]
public async Task RenderAsync_UsesPageExecutionFeatureFromRequest_ToWrapWriter()
{
// Arrange
var pageWriter = CreateBufferedWriter();
var layoutWriter = CreateBufferedWriter();
var layoutExecuted = false;
var count = -1;
var feature = new Mock<IPageExecutionListenerFeature>(MockBehavior.Strict);
feature
.Setup(f => f.DecorateWriter(It.IsAny<RazorTextWriter>()))
.Returns(() =>
{
count++;
if (count == 0)
{
return pageWriter;
}
else if (count == 1)
{
return layoutWriter;
}
throw new Exception();
})
.Verifiable();
var pageContext = Mock.Of<IPageExecutionContext>();
feature
.Setup(f => f.GetContext("/MyPage.cshtml", pageWriter))
.Returns(pageContext)
.Verifiable();
var layoutContext = Mock.Of<IPageExecutionContext>();
feature
.Setup(f => f.GetContext("/Layout.cshtml", layoutWriter))
.Returns(layoutContext)
.Verifiable();
var page = new TestableRazorPage(v =>
{
v.HtmlEncoder = new HtmlTestEncoder();
v.Layout = "Layout";
Assert.Same(pageWriter, v.Output);
Assert.Same(pageContext, v.PageExecutionContext);
});
page.Path = "/MyPage.cshtml";
var layout = new TestableRazorPage(v =>
{
v.HtmlEncoder = new HtmlTestEncoder();
Assert.Same(layoutWriter, v.Output);
Assert.Same(layoutContext, v.PageExecutionContext);
v.RenderBodyPublic();
layoutExecuted = true;
});
layout.Path = "/Layout.cshtml";
var viewEngine = new Mock<IRazorViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(p => p.GetPage("/MyPage.cshtml", "Layout"))
.Returns(new RazorPageResult("Layout", Enumerable.Empty<string>()));
viewEngine
.Setup(p => p.FindPage(It.IsAny<ActionContext>(), "Layout"))
.Returns(new RazorPageResult("/Layout.cshtml", layout));
var view = new RazorView(
viewEngine.Object,
Mock.Of<IRazorPageActivator>(),
new IRazorPage[0],
page,
new HtmlTestEncoder());
var viewContext = CreateViewContext(view);
viewContext.HttpContext.Features.Set<IPageExecutionListenerFeature>(feature.Object);
// Act
await view.RenderAsync(viewContext);
// Assert
feature.Verify();
Assert.True(layoutExecuted);
}
[Fact]
public async Task RenderAsync_UsesPageExecutionFeatureFromRequest_ToGetExecutionContext()
{
// Arrange
var writer = new StringWriter();
var executed = false;
var feature = new Mock<IPageExecutionListenerFeature>(MockBehavior.Strict);
var pageContext = Mock.Of<IPageExecutionContext>();
feature.Setup(f => f.GetContext("/MyPartialPage.cshtml", It.IsAny<RazorTextWriter>()))
.Returns(pageContext)
.Verifiable();
feature.Setup(f => f.DecorateWriter(It.IsAny<RazorTextWriter>()))
.Returns((RazorTextWriter r) => r)
.Verifiable();
var page = new TestableRazorPage(v =>
{
v.HtmlEncoder = new HtmlTestEncoder();
Assert.IsType<RazorTextWriter>(v.Output);
Assert.Same(pageContext, v.PageExecutionContext);
executed = true;
v.Write("Hello world");
});
page.Path = "/MyPartialPage.cshtml";
var view = new RazorView(
Mock.Of<IRazorViewEngine>(),
Mock.Of<IRazorPageActivator>(),
new IRazorPage[0],
page,
new HtmlTestEncoder());
var viewContext = CreateViewContext(view);
viewContext.Writer = writer;
viewContext.HttpContext.Features.Set<IPageExecutionListenerFeature>(feature.Object);
// Act
await view.RenderAsync(viewContext);
// Assert
feature.Verify();
Assert.True(executed);
Assert.Equal("HtmlEncode[[Hello world]]", viewContext.Writer.ToString());
}
[Fact]
public async Task RenderAsync_DoesNotSetExecutionContextWhenListenerIsNotRegistered()
{
// Arrange
var executed = false;
var page = new TestableRazorPage(v =>
{
Assert.Null(v.PageExecutionContext);
executed = true;
});
var view = new RazorView(
Mock.Of<IRazorViewEngine>(),
Mock.Of<IRazorPageActivator>(),
new IRazorPage[0],
page,
new HtmlTestEncoder());
var viewContext = CreateViewContext(view);
// Act
await view.RenderAsync(viewContext);
// Assert
Assert.True(executed);
}
[Fact]
public async Task RenderAsync_CopiesLayoutPropertyFromViewStart()
{
@ -1718,15 +1560,6 @@ namespace Microsoft.AspNet.Mvc.Razor
Assert.Equal(expected, viewContext.Writer.ToString());
}
private static TextWriter CreateBufferedWriter()
{
var mockWriter = new Mock<TextWriter>();
var bufferedWriter = mockWriter.As<IBufferedTextWriter>();
bufferedWriter.SetupGet(b => b.IsBuffering)
.Returns(true);
return mockWriter.Object;
}
private static ViewContext CreateViewContext(RazorView view)
{
var httpContext = new DefaultHttpContext();

View File

@ -1,14 +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.Collections.Generic;
namespace RazorPageExecutionInstrumentationWebSite
{
public interface IHoldInstrumentationData
{
IEnumerable<InstrumentationData> Values { get; }
void IgnoreFurtherData();
}
}

View File

@ -1,31 +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.
namespace RazorPageExecutionInstrumentationWebSite
{
public class InstrumentationData
{
public InstrumentationData(string filePath, int position, int length, bool isLiteral)
{
FilePath = filePath;
Position = position;
Length = length;
IsLiteral = isLiteral;
}
public string FilePath { get; }
public int Position { get; }
public int Length { get; }
public bool IsLiteral { get; }
public override string ToString()
{
var literal = IsLiteral ? "Literal" : "Non-literal";
return $"{FilePath}: {literal} at {Position} contains {Length} characters.";
}
}
}

View File

@ -0,0 +1,29 @@
// 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.IO;
using Microsoft.AspNet.Http;
using Microsoft.Extensions.DiagnosticAdapter;
namespace RazorPageExecutionInstrumentationWebSite
{
public class RazorPageDiagnosticListener
{
public static readonly object WriterKey = new object();
[DiagnosticName("Microsoft.AspNet.Mvc.Razor.BeginInstrumentationContext")]
public virtual void OnBeginPageInstrumentationContext(
HttpContext httpContext,
string path,
int position,
int length,
bool isLiteral)
{
var literal = isLiteral ? "Literal" : "Non-literal";
var text = $"{path}: {literal} at {position} contains {length} characters.";
var writer = (TextWriter)httpContext.Items[WriterKey];
writer.WriteLine(text);
}
}
}

View File

@ -1,13 +1,10 @@
// 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;
using System.Diagnostics;
using System.IO;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Mvc.Razor.Compilation;
using Microsoft.AspNet.PageExecutionInstrumentation;
using Microsoft.Extensions.DependencyInjection;
namespace RazorPageExecutionInstrumentationWebSite
@ -22,24 +19,24 @@ namespace RazorPageExecutionInstrumentationWebSite
// Add MVC services to the services container.
services.AddMvc();
// Make instrumentation data available in views.
services.AddScoped<TestPageExecutionListenerFeature, TestPageExecutionListenerFeature>();
services.AddScoped<IHoldInstrumentationData>(
provider => provider.GetRequiredService<TestPageExecutionListenerFeature>().Holder);
}
public void Configure(IApplicationBuilder app)
{
var listener = new RazorPageDiagnosticListener();
var diagnosticSource = app.ApplicationServices.GetRequiredService<DiagnosticListener>();
diagnosticSource.SubscribeWithAdapter(listener);
app.UseCultureReplacer();
// Execute views with instrumentation enabled.
app.Use((HttpContext context, Func<Task> next) =>
app.Use(async (context, next) =>
{
var listenerFeature = context.RequestServices.GetRequiredService<TestPageExecutionListenerFeature>();
context.Features.Set<IPageExecutionListenerFeature>(listenerFeature);
return next();
using (var writer = new StreamWriter(context.Response.Body))
{
context.Items[RazorPageDiagnosticListener.WriterKey] = writer;
context.Response.Body = Stream.Null;
await next();
}
});
// Add MVC to the request pipeline

View File

@ -1,57 +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.Collections.Generic;
using System.IO;
using Microsoft.AspNet.PageExecutionInstrumentation;
namespace RazorPageExecutionInstrumentationWebSite
{
public class TestPageExecutionListenerFeature : IPageExecutionListenerFeature
{
private readonly TestPageExecutionContext _executionContext = new TestPageExecutionContext();
public IHoldInstrumentationData Holder => _executionContext;
public TextWriter DecorateWriter(TextWriter writer)
{
return writer;
}
public IPageExecutionContext GetContext(string sourceFilePath, TextWriter writer)
{
_executionContext.FilePath = sourceFilePath;
return _executionContext;
}
private class TestPageExecutionContext : IHoldInstrumentationData, IPageExecutionContext
{
private readonly List<InstrumentationData> _values = new List<InstrumentationData>();
private bool _ignoreNewData;
public string FilePath { get; set; }
public IEnumerable<InstrumentationData> Values => _values;
public void IgnoreFurtherData()
{
_ignoreNewData = true;
}
public void BeginContext(int position, int length, bool isLiteral)
{
if (_ignoreNewData)
{
return;
}
_values.Add(new InstrumentationData(FilePath, position, length, isLiteral));
}
public void EndContext()
{
}
}
}
}

View File

@ -1,12 +1,4 @@
@inject RazorPageExecutionInstrumentationWebSite.IHoldInstrumentationData Holder
<div>
<div>
@int.MaxValue
@RenderBody()
</div>
@{
Holder.IgnoreFurtherData();
foreach (var data in Holder.Values)
{
<p>@data.ToString()</p>
}
}

View File

@ -1,18 +1,19 @@
{
"commands": {
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
},
"dependencies": {
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
"Microsoft.AspNet.Mvc": "6.0.0-*",
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
},
"frameworks": {
"dnx451": { },
"dnxcore50": { }
},
"webroot": "wwwroot"
"commands": {
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
},
"dependencies": {
"Microsoft.AspNet.Mvc": "6.0.0-*",
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
"Microsoft.AspNet.StaticFiles": "1.0.0-*",
"Microsoft.Extensions.DiagnosticAdapter": "1.0.0-*"
},
"frameworks": {
"dnx451": { },
"dnxcore50": { }
},
"webroot": "wwwroot"
}