From 2810858905275972ee405b1e64be43dce6258c06 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Sun, 17 Jan 2016 22:59:59 -0800 Subject: [PATCH] Add `HtmlEncoder` parameter to `RazorPage.StartTagHelperWritingScope()` - aspnet/Razor#643 part 2: react to aspnet/Razor#653 - change test calls and delegates to include new parameter - add tests specifically of the new feature - add tag helpers using new feature to `TagHelpersTest` functional test - note `HtmlEncoder`s used elsewhere e.g. in other `RazorPage` instances are unaffected - i.e. changing one `RazorPage.HtmlEncoder` property only affects C# expressions in that page Also simplify scope management, removing bizarre assertion when user does something odd. nits: - correct `// Act` and `// Act & Assert` content - remove #YOLO wrapping --- src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs | 83 ++++---- .../TagHelpersTest.cs | 27 +++ ...HelpersWebSite.Encoders.CustomEncoder.html | 16 ++ .../TagHelpersWebSite.Encoders.Index.html | 15 ++ ...agHelpersWebSite.Encoders.NullEncoder.html | 16 ++ ...HelpersWebSite.Encoders.ThreeEncoders.html | 17 ++ ...agHelpersWebSite.Encoders.TwoEncoders.html | 17 ++ .../RazorPageTest.cs | 184 +++++++++++------- .../TagHelpers/UrlResolutionTagHelperTest.cs | 12 +- .../AnchorTagHelperTest.cs | 10 +- .../CacheTagHelperTest.cs | 4 +- .../EnvironmentTagHelperTest.cs | 2 +- .../FormTagHelperTest.cs | 16 +- .../ImageTagHelperTest.cs | 5 +- .../InputTagHelperTest.cs | 20 +- .../LabelTagHelperTest.cs | 2 +- .../LinkTagHelperTest.cs | 3 +- .../OptionTagHelperTest.cs | 9 +- .../RenderAtEndOfFormTagHelperTest.cs | 4 +- .../ScriptTagHelperTest.cs | 3 +- .../SelectTagHelperTest.cs | 10 +- .../TagHelperOutputExtensionsTest.cs | 45 +++-- .../TextAreaTagHelperTest.cs | 2 +- .../ValidationMessageTagHelperTest.cs | 11 +- .../ValidationSummaryTagHelperTest.cs | 14 +- .../Controllers/EncodersController.cs | 44 +++++ .../TagHelpers/CustomEncoderTagHelper.cs | 81 ++++++++ .../TagHelpers/DefaultEncoderTagHelper.cs | 26 +++ .../TagHelpers/NullEncoderTagHelper.cs | 26 +++ .../Views/Encoders/CustomEncoder.cshtml | 9 + .../Views/Encoders/Index.cshtml | 9 + .../Views/Encoders/NullEncoder.cshtml | 9 + .../Views/Encoders/ThreeEncoders.cshtml | 11 ++ .../Views/Encoders/TwoEncoders.cshtml | 10 + .../Views/Encoders/_Layout.cshtml | 12 ++ .../Views/Encoders/_ViewImports.cshtml | 1 + .../Views/Encoders/_ViewStart.cshtml | 3 + test/WebSites/TagHelpersWebSite/project.json | 4 +- .../TagHelpersWebSite/wwwroot/web.config | 9 + 39 files changed, 617 insertions(+), 184 deletions(-) create mode 100644 test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.CustomEncoder.html create mode 100644 test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.Index.html create mode 100644 test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.NullEncoder.html create mode 100644 test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.ThreeEncoders.html create mode 100644 test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.TwoEncoders.html create mode 100644 test/WebSites/TagHelpersWebSite/Controllers/EncodersController.cs create mode 100644 test/WebSites/TagHelpersWebSite/TagHelpers/CustomEncoderTagHelper.cs create mode 100644 test/WebSites/TagHelpersWebSite/TagHelpers/DefaultEncoderTagHelper.cs create mode 100644 test/WebSites/TagHelpersWebSite/TagHelpers/NullEncoderTagHelper.cs create mode 100644 test/WebSites/TagHelpersWebSite/Views/Encoders/CustomEncoder.cshtml create mode 100644 test/WebSites/TagHelpersWebSite/Views/Encoders/Index.cshtml create mode 100644 test/WebSites/TagHelpersWebSite/Views/Encoders/NullEncoder.cshtml create mode 100644 test/WebSites/TagHelpersWebSite/Views/Encoders/ThreeEncoders.cshtml create mode 100644 test/WebSites/TagHelpersWebSite/Views/Encoders/TwoEncoders.cshtml create mode 100644 test/WebSites/TagHelpersWebSite/Views/Encoders/_Layout.cshtml create mode 100644 test/WebSites/TagHelpersWebSite/Views/Encoders/_ViewImports.cshtml create mode 100644 test/WebSites/TagHelpersWebSite/Views/Encoders/_ViewStart.cshtml create mode 100644 test/WebSites/TagHelpersWebSite/wwwroot/web.config diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs index 5be9ecb71e..0045efd44c 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs @@ -30,8 +30,7 @@ namespace Microsoft.AspNet.Mvc.Razor public abstract class RazorPage : IRazorPage { private readonly HashSet _renderedSections = new HashSet(StringComparer.OrdinalIgnoreCase); - private readonly Stack _writerScopes; - private TextWriter _originalWriter; + private readonly Stack _tagHelperScopes = new Stack(); private IUrlHelper _urlHelper; private ITagHelperActivator _tagHelperActivator; private ITypeActivatorCache _typeActivatorCache; @@ -44,7 +43,6 @@ namespace Microsoft.AspNet.Mvc.Razor public RazorPage() { SectionWriters = new Dictionary(StringComparer.OrdinalIgnoreCase); - _writerScopes = new Stack(); } /// @@ -62,7 +60,8 @@ namespace Microsoft.AspNet.Mvc.Razor public string Layout { get; set; } /// - /// Gets the to be used for encoding HTML. + /// Gets the to use when this + /// handles non- C# expressions. /// [RazorInject] public HtmlEncoder HtmlEncoder { get; set; } @@ -116,7 +115,7 @@ namespace Microsoft.AspNet.Mvc.Razor public IDictionary PreviousSectionWriters { get; set; } /// - public IDictionary SectionWriters { get; private set; } + public IDictionary SectionWriters { get; } /// public abstract Task ExecuteAsync(); @@ -201,28 +200,31 @@ namespace Microsoft.AspNet.Mvc.Razor } /// - /// Starts a new writing scope. + /// Starts a new writing scope and optionally overrides within that scope. /// + /// + /// The to use when this handles + /// non- C# expressions. If null, does not change . + /// /// /// All writes to the or after calling this method will /// be buffered until is called. /// - public void StartTagHelperWritingScope() + public void StartTagHelperWritingScope(HtmlEncoder encoder) { - // If there isn't a base writer take the ViewContext.Writer - if (_originalWriter == null) - { - _originalWriter = ViewContext.Writer; - } + _tagHelperScopes.Push(new TagHelperScopeInfo(HtmlEncoder, ViewContext.Writer)); - var buffer = new ViewBuffer(BufferScope, Path); - var writer = new HtmlContentWrapperTextWriter(buffer, _originalWriter.Encoding); + // If passed an HtmlEncoder, override the property. + if (encoder != null) + { + HtmlEncoder = encoder; + } // We need to replace the ViewContext's Writer to ensure that all content (including content written // from HTML helpers) is redirected. + var buffer = new ViewBuffer(BufferScope, Path); + var writer = new HtmlContentWrapperTextWriter(buffer, ViewContext.Writer.Encoding); ViewContext.Writer = writer; - - _writerScopes.Push(writer); } /// @@ -231,28 +233,21 @@ namespace Microsoft.AspNet.Mvc.Razor /// The buffered . public TagHelperContent EndTagHelperWritingScope() { - if (_writerScopes.Count == 0) + if (_tagHelperScopes.Count == 0) { throw new InvalidOperationException(Resources.RazorPage_ThereIsNoActiveWritingScopeToEnd); } - var writer = _writerScopes.Pop(); - Debug.Assert(writer == ViewContext.Writer); - - if (_writerScopes.Count > 0) - { - ViewContext.Writer = _writerScopes.Peek(); - } - else - { - ViewContext.Writer = _originalWriter; - - // No longer a base writer - _originalWriter = null; - } - + // Get the content written during the current scope. + var writer = ViewContext.Writer as HtmlContentWrapperTextWriter; var tagHelperContent = new DefaultTagHelperContent(); - tagHelperContent.AppendHtml(writer.ContentBuilder); + tagHelperContent.AppendHtml(writer?.ContentBuilder); + + // Restore previous scope. + var scopeInfo = _tagHelperScopes.Pop(); + HtmlEncoder = scopeInfo.Encoder; + ViewContext.Writer = scopeInfo.Writer; + return tagHelperContent; } @@ -290,7 +285,9 @@ namespace Microsoft.AspNet.Mvc.Razor /// Writes the specified with HTML encoding to given . /// /// The instance to write to. - /// The to use when encoding . + /// + /// The to use when encoding . + /// /// The to write. /// /// s of type are written using @@ -825,9 +822,8 @@ namespace Microsoft.AspNet.Mvc.Razor /// public async Task FlushAsync() { - // If there are active writing scopes then we should throw. Cannot flush content that has the potential to - // change. - if (_writerScopes.Count > 0) + // If there are active scopes, then we should throw. Cannot flush content that has the potential to change. + if (_tagHelperScopes.Count > 0) { throw new InvalidOperationException( Resources.FormatRazorPage_CannotFlushWhileInAWritingScope(nameof(FlushAsync), Path)); @@ -1000,5 +996,18 @@ namespace Microsoft.AspNet.Mvc.Razor public bool Suppressed { get; set; } } + + private struct TagHelperScopeInfo + { + public TagHelperScopeInfo(HtmlEncoder encoder, TextWriter writer) + { + Encoder = encoder; + Writer = writer; + } + + public HtmlEncoder Encoder { get; } + + public TextWriter Writer { get; } + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/TagHelpersTest.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/TagHelpersTest.cs index 446a074594..a6b9c5446c 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/TagHelpersTest.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/TagHelpersTest.cs @@ -253,6 +253,33 @@ page:root-content" PlatformNormalizer.NormalizeContent(expectedContent), responseContent, ignoreLineEndingDifferences: true); +#endif + } + + [Theory] + [InlineData("Index")] + [InlineData("CustomEncoder")] + [InlineData("NullEncoder")] + [InlineData("TwoEncoders")] + [InlineData("ThreeEncoders")] + public async Task EncodersPages_ReturnExpectedContent(string actionName) + { + // Arrange + var outputFile = $"compiler/resources/TagHelpersWebSite.Encoders.{ actionName }.html"; + var expectedContent = + await ResourceFile.ReadResourceAsync(_resourcesAssembly, outputFile, sourceFile: false); + + // Act + var response = await Client.GetAsync($"/Encoders/{ actionName }"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var responseContent = await response.Content.ReadAsStringAsync(); + +#if GENERATE_BASELINES + ResourceFile.UpdateFile(_resourcesAssembly, outputFile, expectedContent, responseContent); +#else + Assert.Equal(expectedContent, responseContent, ignoreLineEndingDifferences: true); #endif } } diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.CustomEncoder.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.CustomEncoder.html new file mode 100644 index 0000000000..c0d42ca346 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.CustomEncoder.html @@ -0,0 +1,16 @@ + + + + Using a custom HTML encoder - My MVC 6 Application + + +

MVC 6 - Using a custom HTML encoder

+
+ + +
Custom encoder: Custom[[Outer knows 1 < 4]]
+Custom[[Inner knows 1 < 4]]
Outer knows <b>2 < 4</b> +Inner knows <b>2 < 4</b>
+
+ + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.Index.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.Index.html new file mode 100644 index 0000000000..41fc219acc --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.Index.html @@ -0,0 +1,15 @@ + + + + Using the default HTML encoder - My MVC 6 Application + + +

MVC 6 - Using the default HTML encoder

+
+ + +
Default encoder: Outer knows <b>1 < 4</b>
+
Default encoder: Inner knows <b>1 < 4</b>
+
+ + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.NullEncoder.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.NullEncoder.html new file mode 100644 index 0000000000..0c693004db --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.NullEncoder.html @@ -0,0 +1,16 @@ + + + + Using the null HTML encoder - My MVC 6 Application + + +

MVC 6 - Using the null HTML encoder

+
+ + +
Outer knows <b>2 < 4</b>
+Inner knows <b>2 < 4</b>
Null encoder: Outer knows 1 < 4 +Inner knows 1 < 4
+
+ + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.ThreeEncoders.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.ThreeEncoders.html new file mode 100644 index 0000000000..ebf91357fb --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.ThreeEncoders.html @@ -0,0 +1,17 @@ + + + + Using three HTML encoders - My MVC 6 Application + + +

MVC 6 - Using three HTML encoders

+
+ + +
Custom encoder: Custom[[Outer knows 1 < 4]]
+
Default encoder: Custom[[Inner knows 1 < 4]]

Default encoder: Outer knows <b>2 < 4</b> +
Default encoder: Inner knows <b>2 < 4</b>

Null encoder: Outer knows 3 < 4 +
Default encoder: Inner knows 3 < 4
+
+ + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.TwoEncoders.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.TwoEncoders.html new file mode 100644 index 0000000000..53b8fd8475 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Encoders.TwoEncoders.html @@ -0,0 +1,17 @@ + + + + Using two HTML encoders - My MVC 6 Application + + +

MVC 6 - Using two HTML encoders

+
+ + +
Custom encoder: Custom[[Outer knows 1 < 4]]
+Custom[[Inner knows 1 < 4]]
Outer knows <b>3 < 4</b> +Inner knows <b>3 < 4</b>
Null encoder: Outer knows 2 < 4 +Inner knows 2 < 4
+
+ + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs index 9d533c1281..395b4185b9 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNet.Html; using Microsoft.AspNet.Http.Internal; @@ -41,7 +42,7 @@ namespace Microsoft.AspNet.Mvc.Razor { v.HtmlEncoder = new HtmlTestEncoder(); v.Write("Hello Prefix"); - v.StartTagHelperWritingScope(); + v.StartTagHelperWritingScope(encoder: null); v.Write("Hello from Output"); v.ViewContext.Writer.Write("Hello from view context writer"); var scopeValue = v.EndTagHelperWritingScope(); @@ -54,8 +55,10 @@ namespace Microsoft.AspNet.Mvc.Razor var pageOutput = page.Output.ToString(); // Assert - Assert.Equal("HtmlEncode[[Hello Prefix]]HtmlEncode[[From Scope: ]]HtmlEncode[[Hello from Output]]" + - "Hello from view context writer", pageOutput); + Assert.Equal( + "HtmlEncode[[Hello Prefix]]HtmlEncode[[From Scope: ]]HtmlEncode[[Hello from Output]]" + + "Hello from view context writer", + pageOutput); } [Fact] @@ -67,7 +70,7 @@ namespace Microsoft.AspNet.Mvc.Razor { v.HtmlEncoder = new HtmlTestEncoder(); v.Write("Hello Prefix"); - v.StartTagHelperWritingScope(); + v.StartTagHelperWritingScope(encoder: null); v.Write("Hello In Scope"); var scopeValue = v.EndTagHelperWritingScope(); v.Write("From Scope: "); @@ -91,10 +94,10 @@ namespace Microsoft.AspNet.Mvc.Razor { v.HtmlEncoder = new HtmlTestEncoder(); v.Write("Hello Prefix"); - v.StartTagHelperWritingScope(); + v.StartTagHelperWritingScope(encoder: null); v.Write("Hello In Scope Pre Nest"); - v.StartTagHelperWritingScope(); + v.StartTagHelperWritingScope(encoder: null); v.Write("Hello In Nested Scope"); var scopeValue1 = v.EndTagHelperWritingScope(); @@ -108,36 +111,85 @@ namespace Microsoft.AspNet.Mvc.Razor // Act await page.ExecuteAsync(); - var pageOutput = page.Output.ToString(); // Assert - Assert.Equal("HtmlEncode[[Hello Prefix]]HtmlEncode[[From Scopes: ]]HtmlEncode[[Hello In Scope Pre Nest]]" + - "HtmlEncode[[Hello In Scope Post Nest]]HtmlEncode[[Hello In Nested Scope]]", pageOutput); + var pageOutput = page.Output.ToString(); + Assert.Equal( + "HtmlEncode[[Hello Prefix]]HtmlEncode[[From Scopes: ]]HtmlEncode[[Hello In Scope Pre Nest]]" + + "HtmlEncode[[Hello In Scope Post Nest]]HtmlEncode[[Hello In Nested Scope]]", + pageOutput); } [Fact] - public async Task StartNewWritingScope_CannotFlushInWritingScope() + public async Task StartTagHelperWritingScope_CannotFlushInWritingScope() { // Arrange var viewContext = CreateViewContext(); var page = CreatePage(async v => { v.Path = "/Views/TestPath/Test.cshtml"; - v.StartTagHelperWritingScope(); + v.StartTagHelperWritingScope(encoder: null); await v.FlushAsync(); }); + // Act & Assert + var ex = await Assert.ThrowsAsync(() => page.ExecuteAsync()); + Assert.Equal( + "The FlushAsync operation cannot be performed while " + + "inside a writing scope in '/Views/TestPath/Test.cshtml'.", + ex.Message); + } + + public static TheoryData HtmlEncoderData + { + get + { + return new TheoryData + { + HtmlEncoder.Default, + NullHtmlEncoder.Default, + new HtmlTestEncoder(), + }; + } + } + + [Theory] + [MemberData(nameof(HtmlEncoderData))] + public async Task StartTagHelperWritingScope_SetsHtmlEncoder(HtmlEncoder encoder) + { + // Arrange + var page = CreatePage(v => + { + v.StartTagHelperWritingScope(encoder); + }); + // Act - var ex = await Assert.ThrowsAsync( - () => page.ExecuteAsync()); + await page.ExecuteAsync(); // Assert - Assert.Equal("The FlushAsync operation cannot be performed while " + - "inside a writing scope in '/Views/TestPath/Test.cshtml'.", ex.Message); + Assert.Same(encoder, page.HtmlEncoder); } [Fact] - public async Task StartNewWritingScope_CannotEndWritingScopeWhenNoWritingScope() + public async Task StartTagHelperWritingScope_DoesNotSetHtmlEncoderToNull() + { + // Arrange + var page = CreatePage(v => + { + v.StartTagHelperWritingScope(encoder: null); + }); + var originalEncoder = page.HtmlEncoder; + + // Act + await page.ExecuteAsync(); + + // Assert + Assert.NotNull(originalEncoder); + Assert.Same(originalEncoder, page.HtmlEncoder); + } + + [Fact] + public async Task EndTagHelperWritingScope_CannotEndWritingScopeWhenNoWritingScope() { // Arrange var viewContext = CreateViewContext(); @@ -146,11 +198,8 @@ namespace Microsoft.AspNet.Mvc.Razor v.EndTagHelperWritingScope(); }); - // Act - var ex = await Assert.ThrowsAsync( - () => page.ExecuteAsync()); - - // Assert + // Act & Assert + var ex = await Assert.ThrowsAsync(() => page.ExecuteAsync()); Assert.Equal("There is no active writing scope to end.", ex.Message); } @@ -159,12 +208,10 @@ namespace Microsoft.AspNet.Mvc.Razor { // Arrange var viewContext = CreateViewContext(); - - // Act var page = CreatePage(v => { v.HtmlEncoder = new HtmlTestEncoder(); - v.StartTagHelperWritingScope(); + v.StartTagHelperWritingScope(encoder: null); v.Write("Hello World!"); var returnValue = v.EndTagHelperWritingScope(); @@ -172,6 +219,8 @@ namespace Microsoft.AspNet.Mvc.Razor var content = Assert.IsType(returnValue); Assert.Equal("HtmlEncode[[Hello World!]]", content.GetContent()); }); + + // Act & Assert await page.ExecuteAsync(); } @@ -186,11 +235,8 @@ namespace Microsoft.AspNet.Mvc.Razor v.DefineSection("qux", _nullRenderAsyncDelegate); }); - // Act - var ex = await Assert.ThrowsAsync( - () => page.ExecuteAsync()); - - // Assert + // Act & Assert + var ex = await Assert.ThrowsAsync(() => page.ExecuteAsync()); Assert.Equal("Section 'qux' is already defined.", ex.Message); } @@ -227,10 +273,8 @@ namespace Microsoft.AspNet.Mvc.Razor ex = Assert.Throws(() => v.RenderSection("bar")); }); - // Act + // Act & Assert await page.ExecuteAsync(); - - // Assert Assert.Equal("RenderSection invocation in '/Views/TestPath/Test.cshtml' is invalid. " + "RenderSection can only be called from a layout page.", ex.Message); @@ -250,10 +294,8 @@ namespace Microsoft.AspNet.Mvc.Razor { "baz", _nullRenderAsyncDelegate } }; - // Act + // Act & Assert var ex = await Assert.ThrowsAsync(() => page.ExecuteAsync()); - - // Assert Assert.Equal("Section 'bar' is not defined in path '/Views/TestPath/Test.cshtml'.", ex.Message); } @@ -265,9 +307,9 @@ namespace Microsoft.AspNet.Mvc.Razor { v.Path = "/Views/TestPath/Test.cshtml"; }); - - // Act and Assert page.ExecuteAsync(); + + // Act & Assert ExceptionAssert.Throws(() => page.IsSectionDefined("foo"), "IsSectionDefined invocation in '/Views/TestPath/Test.cshtml' is invalid." + " IsSectionDefined can only be called from a layout page."); @@ -337,12 +379,12 @@ namespace Microsoft.AspNet.Mvc.Razor { "header", _nullRenderAsyncDelegate } }; - // Act + // Act & Assert var ex = await Assert.ThrowsAsync(page.ExecuteAsync); - - // Assert - Assert.Equal("RenderSectionAsync invocation in '/Views/TestPath/Test.cshtml' is invalid." + - " The section 'header' has already been rendered.", ex.Message); + Assert.Equal( + "RenderSectionAsync invocation in '/Views/TestPath/Test.cshtml' is invalid." + + " The section 'header' has already been rendered.", + ex.Message); } [Fact] @@ -361,12 +403,12 @@ namespace Microsoft.AspNet.Mvc.Razor { "header", _nullRenderAsyncDelegate } }; - // Act + // Act & Assert var ex = await Assert.ThrowsAsync(page.ExecuteAsync); - - // Assert - Assert.Equal("RenderSectionAsync invocation in '/Views/TestPath/Test.cshtml' is invalid." + - " The section 'header' has already been rendered.", ex.Message); + Assert.Equal( + "RenderSectionAsync invocation in '/Views/TestPath/Test.cshtml' is invalid." + + " The section 'header' has already been rendered.", + ex.Message); } [Fact] @@ -385,12 +427,12 @@ namespace Microsoft.AspNet.Mvc.Razor { "header", _nullRenderAsyncDelegate } }; - // Act + // Act & Assert var ex = await Assert.ThrowsAsync(page.ExecuteAsync); - - // Assert - Assert.Equal("RenderSectionAsync invocation in '/Views/TestPath/Test.cshtml' is invalid." + - " The section 'header' has already been rendered.", ex.Message); + Assert.Equal( + "RenderSectionAsync invocation in '/Views/TestPath/Test.cshtml' is invalid." + + " The section 'header' has already been rendered.", + ex.Message); } [Fact] @@ -404,12 +446,12 @@ namespace Microsoft.AspNet.Mvc.Razor await v.RenderSectionAsync("header"); }); - // Act + // Act & Assert var ex = await Assert.ThrowsAsync(page.ExecuteAsync); - - // Assert - Assert.Equal("RenderSectionAsync invocation in '/Views/TestPath/Test.cshtml' is invalid. " + - "RenderSectionAsync can only be called from a layout page.", ex.Message); + Assert.Equal( + "RenderSectionAsync invocation in '/Views/TestPath/Test.cshtml' is invalid. " + + "RenderSectionAsync can only be called from a layout page.", + ex.Message); } [Fact] @@ -422,12 +464,10 @@ namespace Microsoft.AspNet.Mvc.Razor }); page.Path = path; page.BodyContent = new HtmlString("some content"); - - // Act await page.ExecuteAsync(); - var ex = Assert.Throws(() => page.EnsureRenderedBodyOrSections()); - // Assert + // Act & Assert + var ex = Assert.Throws(() => page.EnsureRenderedBodyOrSections()); Assert.Equal($"RenderBody has not been called for the page at '{path}'.", ex.Message); } @@ -446,14 +486,14 @@ namespace Microsoft.AspNet.Mvc.Razor { { sectionName, _nullRenderAsyncDelegate } }; - - // Act await page.ExecuteAsync(); - var ex = Assert.Throws(() => page.EnsureRenderedBodyOrSections()); - // Assert - Assert.Equal("The following sections have been defined but have not been rendered by the page at " + - $"'{path}': '{sectionName}'.", ex.Message); + // Act & Assert + var ex = Assert.Throws(() => page.EnsureRenderedBodyOrSections()); + Assert.Equal( + "The following sections have been defined but have not been rendered by the page at " + + $"'{path}': '{sectionName}'.", + ex.Message); } [Fact] @@ -474,7 +514,7 @@ namespace Microsoft.AspNet.Mvc.Razor { sectionB, _nullRenderAsyncDelegate }, }; - // Act and Assert + // Act & Assert (does not throw) await page.ExecuteAsync(); page.EnsureRenderedBodyOrSections(); } @@ -593,7 +633,7 @@ namespace Microsoft.AspNet.Mvc.Razor await p.FlushAsync(); }, context); - // Act and Assert + // Act & Assert var ex = await Assert.ThrowsAsync(() => page.ExecuteAsync()); Assert.Equal(expected, ex.Message); } @@ -923,7 +963,7 @@ namespace Microsoft.AspNet.Mvc.Razor items: new Dictionary(), uniqueId: string.Empty, executeChildContentAsync: () => Task.FromResult(result: true), - startTagHelperWritingScope: () => { }, + startTagHelperWritingScope: _ => { }, endTagHelperWritingScope: () => new DefaultTagHelperContent()); // Act @@ -964,7 +1004,7 @@ namespace Microsoft.AspNet.Mvc.Razor items: new Dictionary(), uniqueId: string.Empty, executeChildContentAsync: () => Task.FromResult(result: true), - startTagHelperWritingScope: () => { }, + startTagHelperWritingScope: _ => { }, endTagHelperWritingScope: () => new DefaultTagHelperContent()); // Act @@ -992,7 +1032,7 @@ namespace Microsoft.AspNet.Mvc.Razor items: new Dictionary(), uniqueId: string.Empty, executeChildContentAsync: () => Task.FromResult(result: true), - startTagHelperWritingScope: () => { }, + startTagHelperWritingScope: _ => { }, endTagHelperWritingScope: () => new DefaultTagHelperContent()); // Act diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/TagHelpers/UrlResolutionTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/TagHelpers/UrlResolutionTagHelperTest.cs index eebf952e69..e2b5f25e8f 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/TagHelpers/UrlResolutionTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/TagHelpers/UrlResolutionTagHelperTest.cs @@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Mvc.Razor.TagHelpers { { "href", url } }, - getChildContentAsync: _ => Task.FromResult(null)); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(null)); var urlHelperMock = new Mock(); urlHelperMock .Setup(urlHelper => urlHelper.Content(It.IsAny())) @@ -103,7 +103,7 @@ namespace Microsoft.AspNet.Mvc.Razor.TagHelpers { { "href", url } }, - getChildContentAsync: _ => Task.FromResult(null)); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(null)); var urlHelperMock = new Mock(); urlHelperMock .Setup(urlHelper => urlHelper.Content(It.IsAny())) @@ -158,7 +158,7 @@ namespace Microsoft.AspNet.Mvc.Razor.TagHelpers { { "href", url } }, - getChildContentAsync: _ => Task.FromResult(null)); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(null)); var urlHelperMock = new Mock(); urlHelperMock .Setup(urlHelper => urlHelper.Content(It.IsAny())) @@ -213,7 +213,7 @@ namespace Microsoft.AspNet.Mvc.Razor.TagHelpers { { "href", url } }, - getChildContentAsync: _ => Task.FromResult(null)); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(null)); var urlHelperMock = new Mock(); urlHelperMock .Setup(urlHelper => urlHelper.Content(It.IsAny())) @@ -251,7 +251,7 @@ namespace Microsoft.AspNet.Mvc.Razor.TagHelpers { { "href", true } }, - getChildContentAsync: _ => Task.FromResult(null)); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(null)); var tagHelper = new UrlResolutionTagHelper(urlHelperFactory: null, htmlEncoder: null); var context = new TagHelperContext( @@ -288,7 +288,7 @@ namespace Microsoft.AspNet.Mvc.Razor.TagHelpers { { "href", new HtmlString(relativeUrl) } }, - getChildContentAsync: _ => Task.FromResult(null)); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(null)); var urlHelperMock = new Mock(); urlHelperMock .Setup(urlHelper => urlHelper.Content(It.IsAny())) diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs index ae4fe0be71..7a9a5e5769 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs @@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "id", "myanchor" }, }, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something Else"); @@ -99,7 +99,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "a", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -148,7 +148,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "a", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -209,7 +209,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "href", "http://www.contoso.com" } }, - getChildContentAsync: _ => Task.FromResult(null)); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(null)); if (propertyName == "asp-route-") { anchorTagHelper.RouteValues.Add("name", "value"); @@ -255,7 +255,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "a", attributes: new TagHelperAttributeList(), - getChildContentAsync: _ => Task.FromResult(null)); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(null)); var expectedErrorMessage = "Cannot determine an 'href' attribute for . An with a specified " + "'asp-route' must not have an 'asp-action' or 'asp-controller' attribute."; diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/CacheTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/CacheTagHelperTest.cs index 6997003800..83074e95b7 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/CacheTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/CacheTagHelperTest.cs @@ -740,7 +740,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( "cache", new TagHelperAttributeList { { "attr", "value" } }, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { TagHelperContent tagHelperContent; if (!cache.TryGetValue("key1", out tagHelperContent)) @@ -806,7 +806,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers return new TagHelperOutput( tagName, attributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetHtmlContent(childContent); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/EnvironmentTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/EnvironmentTagHelperTest.cs index 186bdef010..1283909176 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/EnvironmentTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/EnvironmentTagHelperTest.cs @@ -143,7 +143,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Test return new TagHelperOutput( tagName, attributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent(childContent); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs index f7dd1b0768..32c8f44c4c 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs @@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "id", "myform" }, }, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something Else"); @@ -116,7 +116,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "form", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -168,7 +168,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "form", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -239,7 +239,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "form", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -290,7 +290,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "form", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -357,7 +357,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "aCTiON", "my-action" }, }, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -397,7 +397,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "action", "my-action" }, }, - getChildContentAsync: _ => Task.FromResult(null)); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(null)); if (propertyName == "asp-route-") { formTagHelper.RouteValues.Add("name", "value"); @@ -438,7 +438,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "form", attributes: new TagHelperAttributeList(), - getChildContentAsync: _ => Task.FromResult(null)); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(null)); var expectedErrorMessage = "Cannot determine an 'action' attribute for
. A with a specified " + "'asp-route' must not have an 'asp-action' or 'asp-controller' attribute."; diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ImageTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ImageTagHelperTest.cs index eaec7657f9..c778820b97 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ImageTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ImageTagHelperTest.cs @@ -54,7 +54,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "img", outputAttributes, - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var hostingEnvironment = MakeHostingEnvironment(); var viewContext = MakeViewContext(); var urlHelper = new Mock(); @@ -294,7 +295,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers return new TagHelperOutput( "img", attributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent(default(string)); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs index 2d9e8e745e..0c912ff2f8 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs @@ -94,7 +94,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( originalTagName, outputAttributes, - getChildContentAsync: useCachedResult => Task.FromResult(result: null)) + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult(result: null)) { TagMode = TagMode.SelfClosing, }; @@ -204,7 +204,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -268,7 +268,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( originalTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -367,7 +367,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -468,7 +468,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -566,7 +566,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -675,7 +675,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -792,7 +792,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())) + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())) { TagMode = TagMode.SelfClosing, }; @@ -875,7 +876,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())) + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())) { TagMode = TagMode.SelfClosing, }; diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LabelTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LabelTagHelperTest.cs index 23a813e78e..77ea245c77 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LabelTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LabelTagHelperTest.cs @@ -201,7 +201,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, htmlAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.AppendHtml(tagHelperOutputContent.OriginalChildContent); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LinkTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LinkTagHelperTest.cs index aadd202804..1a567dac63 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LinkTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LinkTagHelperTest.cs @@ -844,7 +844,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers return new TagHelperOutput( tagName, attributes, - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); } private static IHostingEnvironment MakeHostingEnvironment() diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/OptionTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/OptionTagHelperTest.cs index 264d07dc2f..18dbe04eae 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/OptionTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/OptionTagHelperTest.cs @@ -408,7 +408,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagHelperOutput.TagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { // GetChildContentAsync should not be invoked since we are setting the content below. Assert.True(false); @@ -478,7 +478,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( originalTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent(originalContent); @@ -542,7 +542,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( originalTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent(originalContent); @@ -574,7 +574,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( tagName, attributes, - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); tagHelperOutput.Content.SetContent(content); return tagHelperOutput; diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/RenderAtEndOfFormTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/RenderAtEndOfFormTagHelperTest.cs index 073f91c1b5..08dfd1526a 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/RenderAtEndOfFormTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/RenderAtEndOfFormTagHelperTest.cs @@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( tagName: "form", attributes: new TagHelperAttributeList(), - getChildContentAsync: (useCachedResult) => + getChildContentAsync: (useCachedResult, encoder) => { Assert.True(viewContext.FormContext.CanRenderAtEndOfForm); foreach (var item in tagBuilderList) @@ -103,7 +103,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers return Task.FromResult(true); }, - startTagHelperWritingScope: () => { }, + startTagHelperWritingScope: _ => { }, endTagHelperWritingScope: () => new DefaultTagHelperContent()); // This TagHelper will pre-execute the child content forcing the body to be cached. diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ScriptTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ScriptTagHelperTest.cs index 0ed12ed685..21fcab7bb6 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ScriptTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ScriptTagHelperTest.cs @@ -847,7 +847,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers return new TagHelperOutput( tagName, attributes, - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); } private static IHostingEnvironment MakeHostingEnvironment() diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs index 630a6286ed..940faa5e83 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs @@ -208,7 +208,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -297,7 +297,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.AppendHtml("Something"); @@ -401,7 +401,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.AppendHtml("Something"); @@ -489,7 +489,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -570,7 +570,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( tagName, originalAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs index 1b6a740d10..5188fc4777 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs @@ -336,7 +336,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( tagName: "p", attributes: new TagHelperAttributeList(outputAttributes), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var context = new TagHelperContext( allAttributes, items: new Dictionary(), @@ -436,7 +437,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( tagName: "p", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var context = new TagHelperContext( allAttributes, items: new Dictionary(), @@ -458,7 +460,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( "p", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.Append("Something"); @@ -492,7 +494,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { attributeName, "world2" } }, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.Append("Something Else"); @@ -523,7 +525,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( "p", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.Append("Something"); @@ -555,7 +557,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "route-Hello", "World" }, { "Route-I", "Am" } }, - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var expectedAttribute = new TagHelperAttribute("type", "btn"); tagHelperOutput.Attributes.Add(expectedAttribute); @@ -582,7 +585,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "route-Hello", "World" }, { "Route-I", "Am" } }, - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var expectedAttribute = new TagHelperAttribute("type", "btn"); tagHelperOutput.Attributes.Add(expectedAttribute); var attributes = tagHelperOutput.Attributes @@ -607,7 +611,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "route-Hello", "World" }, { "Route-I", "Am" } }, - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var expectedAttribute = new TagHelperAttribute("type", "btn"); tagHelperOutput.Attributes.Add(expectedAttribute); @@ -765,7 +770,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( "p", outputAttributes, - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var tagBuilder = new TagBuilder("p"); foreach (var attr in tagBuilderAttributes) @@ -790,7 +796,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( tagName: "p", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var expectedAttribute = new TagHelperAttribute("type", "btn"); tagHelperOutput.Attributes.Add(expectedAttribute); @@ -812,7 +819,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( tagName: "p", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); tagHelperOutput.Attributes.Add("class", "Hello"); var tagBuilder = new TagBuilder("p"); @@ -839,7 +847,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( tagName: "p", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); tagHelperOutput.Attributes.Add(originalName, "Hello"); var tagBuilder = new TagBuilder("p"); @@ -860,7 +869,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( tagName: "p", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var tagBuilder = new TagBuilder("p"); var expectedAttribute = new TagHelperAttribute("visible", "val < 3"); @@ -881,7 +891,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( tagName: "p", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var tagBuilder = new TagBuilder("p"); var expectedAttribute1 = new TagHelperAttribute("class", "btn"); @@ -907,7 +918,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( tagName: "p", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var expectedAttribute = new TagHelperAttribute("class", "btn"); tagHelperOutput.Attributes.Add(expectedAttribute); @@ -928,7 +940,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperOutput = new TagHelperOutput( tagName: "p", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); var expectedOutputAttribute = new TagHelperAttribute("class", "btn"); tagHelperOutput.Attributes.Add(expectedOutputAttribute); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TextAreaTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TextAreaTagHelperTest.cs index 01a7ff2170..c5f001d69b 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TextAreaTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TextAreaTagHelperTest.cs @@ -135,7 +135,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( expectedTagName, htmlAttributes, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationMessageTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationMessageTagHelperTest.cs index 190c1a2eaa..4597209eee 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationMessageTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationMessageTagHelperTest.cs @@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "id", "myvalidationmessage" } }, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -115,7 +115,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "span", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -168,7 +168,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "span", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.AppendHtml(childContent); @@ -227,7 +227,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( "span", attributes: new TagHelperAttributeList(), - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent(childContent); @@ -268,7 +268,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( tagName: "span", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); output.PreContent.SetContent(expectedPreContent); output.Content.SetContent(expectedContent); output.PostContent.SetContent(expectedPostContent); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs index a6f67099e8..c41298013e 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs @@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "class", "form-control" } }, - getChildContentAsync: useCachedResult => + getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); @@ -111,7 +111,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( tagName: "div", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); output.PreContent.SetContent(expectedPreContent); output.Content.SetContent(expectedContent); output.PostContent.SetContent(expectedPostContent); @@ -165,7 +166,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( tagName: "div", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); output.PreContent.SetContent(expectedPreContent); output.Content.SetContent(expectedContent); output.PostContent.SetContent("Content of validation summary"); @@ -213,7 +215,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( tagName: "div", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); output.PreContent.SetContent(expectedPreContent); output.Content.SetContent(expectedContent); output.PostContent.SetContent(expectedPostContent); @@ -268,7 +271,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var output = new TagHelperOutput( tagName: "div", attributes: new TagHelperAttributeList(), - getChildContentAsync: (_) => Task.FromResult(new DefaultTagHelperContent())); + getChildContentAsync: (useCachedResult, encoder) => Task.FromResult( + new DefaultTagHelperContent())); output.PreContent.SetContent(expectedPreContent); output.Content.SetContent(expectedContent); output.PostContent.SetContent("Content of validation message"); diff --git a/test/WebSites/TagHelpersWebSite/Controllers/EncodersController.cs b/test/WebSites/TagHelpersWebSite/Controllers/EncodersController.cs new file mode 100644 index 0000000000..c1a3104cca --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/Controllers/EncodersController.cs @@ -0,0 +1,44 @@ +// 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 Microsoft.AspNet.Mvc; + +namespace TagHelpersWebSite.Controllers +{ + public class EncodersController : Controller + { + public IActionResult Index() + { + ViewData["Title"] = "Using the default HTML encoder"; + return View(); + } + + public IActionResult CustomEncoder() + { + ViewData["Title"] = "Using a custom HTML encoder"; + return View(); + } + + public IActionResult NullEncoder() + { + ViewData["Title"] = "Using the null HTML encoder"; + return View(); + } + + // We've defined the behavior when multiple tag helpers target the same element. But this is an extreme corner + // case since one tag helper even using anything but the default HTML encoder is not going to be common. + public IActionResult TwoEncoders() + { + ViewData["Title"] = "Using two HTML encoders"; + return View(); + } + + // We've defined the behavior when multiple tag helpers target the same element. But this is an extreme corner + // case since one tag helper even using anything but the default HTML encoder is not going to be common. + public IActionResult ThreeEncoders() + { + ViewData["Title"] = "Using three HTML encoders"; + return View(); + } + } +} diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/CustomEncoderTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/CustomEncoderTagHelper.cs new file mode 100644 index 0000000000..428cbe72d4 --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/CustomEncoderTagHelper.cs @@ -0,0 +1,81 @@ +// 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.Text.Encodings.Web; +using System.Threading.Tasks; +using Microsoft.AspNet.Razor.TagHelpers; + +namespace TagHelpersWebSite.TagHelpers +{ + [HtmlTargetElement("pre")] + public class CustomEncoderTagHelper : TagHelper + { + public override int Order => 1; + + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + var encoder = new CustomEncoder(); + var customContent = await output.GetChildContentAsync(encoder); + + // Note this is very unsafe. Should always post-process content that may not be fully HTML encoded before + // writing it into a response. Here for example, could pass SetContent() a string and that would be + // HTML encoded later. + output.PreContent + .SetHtmlContent("Custom encoder: ") + .AppendHtml(customContent) + .AppendHtml("
"); + } + + // Simple encoder that just wraps "string" as "Custom[[string]]". Note: Lacks all parameter checks. + private class CustomEncoder : HtmlEncoder + { + public CustomEncoder() + { + } + + public override int MaxOutputCharactersPerInputCharacter => 1; + + public override string Encode(string value) => $"Custom[[{ value }]]"; + + public override void Encode(TextWriter output, char[] value, int startIndex, int characterCount) + { + if (characterCount == 0) + { + return; + } + + output.Write("Custom[["); + output.Write(value, startIndex, characterCount); + output.Write("]]"); + } + + public override void Encode(TextWriter output, string value, int startIndex, int characterCount) + { + if (characterCount == 0) + { + return; + } + + output.Write("Custom[["); + output.Write(value.Substring(startIndex, characterCount)); + output.Write("]]"); + } + + public override unsafe int FindFirstCharacterToEncode(char* text, int textLength) => -1; + + public override unsafe bool TryEncodeUnicodeScalar( + int unicodeScalar, + char* buffer, + int bufferLength, + out int numberOfCharactersWritten) + { + numberOfCharactersWritten = 0; + + return false; + } + + public override bool WillEncode(int unicodeScalar) => false; + } + } +} diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/DefaultEncoderTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/DefaultEncoderTagHelper.cs new file mode 100644 index 0000000000..36df03008b --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/DefaultEncoderTagHelper.cs @@ -0,0 +1,26 @@ +// 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.Threading.Tasks; +using Microsoft.AspNet.Razor.TagHelpers; + +namespace TagHelpersWebSite.TagHelpers +{ + [HtmlTargetElement("pre")] + [HtmlTargetElement("inner")] + [OutputElementHint("pre")] + public class DefaultEncoderTagHelper : TagHelper + { + public override int Order => 2; + + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + var defaultContent = await output.GetChildContentAsync(); + + output.Content + .SetHtmlContent("Default encoder: ") + .AppendHtml(defaultContent); + output.TagName = "pre"; + } + } +} diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/NullEncoderTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/NullEncoderTagHelper.cs new file mode 100644 index 0000000000..e814fdb41b --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/NullEncoderTagHelper.cs @@ -0,0 +1,26 @@ +// 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.Threading.Tasks; +using Microsoft.AspNet.Razor.TagHelpers; + +namespace TagHelpersWebSite.TagHelpers +{ + [HtmlTargetElement("pre")] + public class NullEncoderTagHelper : TagHelper + { + public override int Order => 3; + + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + var nullContent = await output.GetChildContentAsync(NullHtmlEncoder.Default); + + // Note this is very unsafe. Should always post-process content that may not be fully HTML encoded before + // writing it into a response. Here for example, could pass SetContent() a string and that would be + // HTML encoded later. + output.PostContent + .SetHtmlContent("
Null encoder: ") + .AppendHtml(nullContent); + } + } +} diff --git a/test/WebSites/TagHelpersWebSite/Views/Encoders/CustomEncoder.cshtml b/test/WebSites/TagHelpersWebSite/Views/Encoders/CustomEncoder.cshtml new file mode 100644 index 0000000000..0f0981d9c2 --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/Views/Encoders/CustomEncoder.cshtml @@ -0,0 +1,9 @@ +@addTagHelper TagHelpersWebSite.TagHelpers.CustomEncoderTagHelper, TagHelpersWebSite + +@{ + var count = 0; + var innerCount = 0; +} + +
@($"Outer knows { ++count } < 4")
+@($"Inner knows { ++innerCount } < 4")
\ No newline at end of file diff --git a/test/WebSites/TagHelpersWebSite/Views/Encoders/Index.cshtml b/test/WebSites/TagHelpersWebSite/Views/Encoders/Index.cshtml new file mode 100644 index 0000000000..41557a5e0e --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/Views/Encoders/Index.cshtml @@ -0,0 +1,9 @@ +@addTagHelper TagHelpersWebSite.TagHelpers.DefaultEncoderTagHelper, TagHelpersWebSite + +@{ + var count = 0; + var innerCount = 0; +} + +
@($"Outer knows { ++count } < 4")
+@($"Inner knows { ++innerCount } < 4")
\ No newline at end of file diff --git a/test/WebSites/TagHelpersWebSite/Views/Encoders/NullEncoder.cshtml b/test/WebSites/TagHelpersWebSite/Views/Encoders/NullEncoder.cshtml new file mode 100644 index 0000000000..f59fb838a1 --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/Views/Encoders/NullEncoder.cshtml @@ -0,0 +1,9 @@ +@addTagHelper TagHelpersWebSite.TagHelpers.NullEncoderTagHelper, TagHelpersWebSite + +@{ + var count = 0; + var innerCount = 0; +} + +
@($"Outer knows { ++count } < 4")
+@($"Inner knows { ++innerCount } < 4")
\ No newline at end of file diff --git a/test/WebSites/TagHelpersWebSite/Views/Encoders/ThreeEncoders.cshtml b/test/WebSites/TagHelpersWebSite/Views/Encoders/ThreeEncoders.cshtml new file mode 100644 index 0000000000..ed91122d9c --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/Views/Encoders/ThreeEncoders.cshtml @@ -0,0 +1,11 @@ +@addTagHelper TagHelpersWebSite.TagHelpers.CustomEncoderTagHelper, TagHelpersWebSite +@addTagHelper TagHelpersWebSite.TagHelpers.DefaultEncoderTagHelper, TagHelpersWebSite +@addTagHelper TagHelpersWebSite.TagHelpers.NullEncoderTagHelper, TagHelpersWebSite + +@{ + var count = 0; + var innerCount = 0; +} + +
@($"Outer knows { ++count } < 4")
+@($"Inner knows { ++innerCount } < 4")
\ No newline at end of file diff --git a/test/WebSites/TagHelpersWebSite/Views/Encoders/TwoEncoders.cshtml b/test/WebSites/TagHelpersWebSite/Views/Encoders/TwoEncoders.cshtml new file mode 100644 index 0000000000..e51bcc22df --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/Views/Encoders/TwoEncoders.cshtml @@ -0,0 +1,10 @@ +@addTagHelper TagHelpersWebSite.TagHelpers.CustomEncoderTagHelper, TagHelpersWebSite +@addTagHelper TagHelpersWebSite.TagHelpers.NullEncoderTagHelper, TagHelpersWebSite + +@{ + var count = 0; + var innerCount = 0; +} + +
@($"Outer knows { ++count } < 4")
+@($"Inner knows { ++innerCount } < 4")
\ No newline at end of file diff --git a/test/WebSites/TagHelpersWebSite/Views/Encoders/_Layout.cshtml b/test/WebSites/TagHelpersWebSite/Views/Encoders/_Layout.cshtml new file mode 100644 index 0000000000..eafd91c010 --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/Views/Encoders/_Layout.cshtml @@ -0,0 +1,12 @@ + + + + @ViewData["Title"] - My MVC 6 Application + + +

MVC 6 - @ViewData["Title"]

+
+ @RenderBody() +
+ + \ No newline at end of file diff --git a/test/WebSites/TagHelpersWebSite/Views/Encoders/_ViewImports.cshtml b/test/WebSites/TagHelpersWebSite/Views/Encoders/_ViewImports.cshtml new file mode 100644 index 0000000000..56ab7d9860 --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/Views/Encoders/_ViewImports.cshtml @@ -0,0 +1 @@ +@removeTagHelper "TagHelpersWebSite.TagHelpers.RootViewStartTagHelper, TagHelpersWebSite" \ No newline at end of file diff --git a/test/WebSites/TagHelpersWebSite/Views/Encoders/_ViewStart.cshtml b/test/WebSites/TagHelpersWebSite/Views/Encoders/_ViewStart.cshtml new file mode 100644 index 0000000000..935cd49e4d --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/Views/Encoders/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "_Layout.cshtml"; +} diff --git a/test/WebSites/TagHelpersWebSite/project.json b/test/WebSites/TagHelpersWebSite/project.json index 03ef2ce5ce..a21df79b90 100644 --- a/test/WebSites/TagHelpersWebSite/project.json +++ b/test/WebSites/TagHelpersWebSite/project.json @@ -1,6 +1,8 @@ { "compilationOptions": { - "emitEntryPoint": true + "allowUnsafe": true, + "emitEntryPoint": true, + "warningsAsErrors": true }, "commands": { "web": "TagHelpersWebSite" diff --git a/test/WebSites/TagHelpersWebSite/wwwroot/web.config b/test/WebSites/TagHelpersWebSite/wwwroot/web.config new file mode 100644 index 0000000000..9a0d90abf8 --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/wwwroot/web.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file