From 2c4c35e126d9287053cdaa772a5f9ca307650f7c Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Mon, 13 Apr 2015 14:52:06 -0700 Subject: [PATCH] Add rendering logic for PreElement and PostElement on TagHelperOutput. - Added unit tests to validate that the properties were rendered correctly. - Modified functional tests to utilize PreElement and PostElement. aspnet/Razor#341 --- src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs | 4 + .../TagHelpersWebSite.Home.Index.html | 4 +- .../RazorPageTest.cs | 362 ++++++++++++++++-- .../TagHelpers/SurroundTagHelper.cs | 30 ++ .../TagHelpersWebSite/Views/Home/Index.cshtml | 6 +- 5 files changed, 362 insertions(+), 44 deletions(-) create mode 100644 test/WebSites/TagHelpersWebSite/TagHelpers/SurroundTagHelper.cs diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs index 5e33869980..6fbb8185fd 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs @@ -278,6 +278,8 @@ namespace Microsoft.AspNet.Mvc.Razor var tagHelperOutput = tagHelperExecutionContext.Output; var isTagNameNullOrWhitespace = string.IsNullOrWhiteSpace(tagHelperOutput.TagName); + WriteTagHelperContentTo(writer, tagHelperOutput.PreElement); + if (!isTagNameNullOrWhitespace) { writer.Write('<'); @@ -324,6 +326,8 @@ namespace Microsoft.AspNet.Mvc.Razor { writer.Write(string.Format(CultureInfo.InvariantCulture, "", tagHelperOutput.TagName)); } + + WriteTagHelperContentTo(writer, tagHelperOutput.PostElement); } private void WriteTagHelperContentTo(TextWriter writer, TagHelperContent content) diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Index.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Index.html index 7e3acce114..bf3bb5485f 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Index.html +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/compiler/resources/TagHelpersWebSite.Home.Index.html @@ -28,12 +28,12 @@
-

This website has not been approved yet. Visit www.contoso.com for more information.

+

This website has not been approved yet. Visit www.contoso.com for more information.

Current Tag Cloud from Tag Helper

-
["Lorem","ipsum","dolor","sit","amet","consectetur","adipisicing","elit","sed","do","eiusmod","tempor","incididunt","ut","labore","et","dolore","magna","aliquaUt","enim"]
+
["Lorem","ipsum","dolor","sit","amet","consectetur","adipisicing","elit","sed","do","eiusmod","tempor","incididunt","ut","labore","et","dolore","magna","aliquaUt","enim"]

Current Tag Cloud from ViewComponentHelper:

["Lorem","ipsum","dolor","sit","amet","consectetur","adipisicing","elit","sed","do","eiusmod","tempor","incididunt","ut","labore"]
diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs index c9fef69fe2..25c2000076 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs @@ -722,85 +722,365 @@ namespace Microsoft.AspNet.Mvc.Razor { { // parameters: TagName, Attributes, SelfClosing, PreContent, Content, PostContent - GetTagHelperOutput("div", new Dictionary(), false, null, "Hello World!", null), + GetTagHelperOutput( + tagName: "div", + attributes: new Dictionary(), + selfClosing: false, + preElement: null, + preContent: null, + content: "Hello World!", + postContent: null, + postElement: null), "
Hello World!
" }, { - GetTagHelperOutput(null, new Dictionary(), false, null, "Hello World!", null), - "Hello World!" - }, - { - GetTagHelperOutput(" ", new Dictionary(), false, null, "Hello World!", null), + GetTagHelperOutput( + tagName: null, + attributes: new Dictionary(), + selfClosing: false, + preElement: null, + preContent: null, + content: "Hello World!", + postContent: null, + postElement: null), "Hello World!" }, { GetTagHelperOutput( - "p", - new Dictionary() { { "test", "testVal" } }, - false, - null, - "Hello World!", - null), + tagName: " ", + attributes: new Dictionary(), + selfClosing: false, + preElement: null, + preContent: null, + content: "Hello World!", + postContent: null, + postElement: null), + "Hello World!" + }, + { + GetTagHelperOutput( + tagName: "p", + attributes: new Dictionary() { { "test", "testVal" } }, + selfClosing: false, + preElement: null, + preContent: null, + content: "Hello World!", + postContent: null, + postElement: null), "

Hello World!

" }, { GetTagHelperOutput( - "p", - new Dictionary() { { "test", "testVal" }, { "something", " spaced " } }, - false, - null, - "Hello World!", - null), + tagName: "p", + attributes: new Dictionary() { { "test", "testVal" }, { "something", " spaced " } }, + selfClosing: false, + preElement: null, + preContent: null, + content: "Hello World!", + postContent: null, + postElement: null), "

Hello World!

" }, { GetTagHelperOutput( - "p", - new Dictionary() { { "test", "testVal" } }, - true, - null, - "Hello World!", - null), + tagName: "p", + attributes: new Dictionary() { { "test", "testVal" } }, + selfClosing: true, + preElement: null, + preContent: null, + content: "Hello World!", + postContent: null, + postElement: null), "

" }, { GetTagHelperOutput( - "p", - new Dictionary() { { "test", "testVal" }, { "something", " spaced " } }, - true, - null, - "Hello World!", - null), + tagName: "p", + attributes: new Dictionary() { { "test", "testVal" }, { "something", " spaced " } }, + selfClosing: true, + preElement: null, + preContent: null, + content: "Hello World!", + postContent: null, + postElement: null), "

" }, { - GetTagHelperOutput("p", new Dictionary(), false, "Hello World!", null, null), + GetTagHelperOutput( + tagName: "p", + attributes: new Dictionary(), + selfClosing: false, + preElement: null, + preContent: "Hello World!", + content: null, + postContent: null, + postElement: null), "

Hello World!

" }, { - GetTagHelperOutput("p", new Dictionary(), false, null, "Hello World!", null), + GetTagHelperOutput( + tagName: "p", + attributes: new Dictionary(), + selfClosing: false, + preElement: null, + preContent: null, + content: "Hello World!", + postContent: null, + postElement: null), "

Hello World!

" }, { - GetTagHelperOutput("p", new Dictionary(), false, null, null, "Hello World!"), + GetTagHelperOutput( + tagName: "p", + attributes: new Dictionary(), + selfClosing: false, + preElement: null, + preContent: null, + content: null, + postContent: "Hello World!", + postElement: null), "

Hello World!

" }, { - GetTagHelperOutput("p", new Dictionary(), false, "Hello", "Test", "World!"), + GetTagHelperOutput( + tagName: "p", + attributes: new Dictionary(), + selfClosing: false, + preElement: null, + preContent: "Hello", + content: "Test", + postContent: "World!", + postElement: null), "

HelloTestWorld!

" }, { - GetTagHelperOutput("p", new Dictionary(), true, "Hello", "Test", "World!"), + GetTagHelperOutput( + tagName: "p", + attributes: new Dictionary(), + selfClosing: true, + preElement: null, + preContent: "Hello", + content: "Test", + postContent: "World!", + postElement: null), "

" }, { - GetTagHelperOutput("custom", new Dictionary(), false, "Hello", "Test", "World!"), + GetTagHelperOutput( + tagName: "custom", + attributes: new Dictionary(), + selfClosing: false, + preElement: null, + preContent: "Hello", + content: "Test", + postContent: "World!", + postElement: null), "HelloTestWorld!" }, { - GetTagHelperOutput("random", new Dictionary(), true, "Hello", "Test", "World!"), + GetTagHelperOutput( + tagName: "random", + attributes: new Dictionary(), + selfClosing: true, + preElement: null, + preContent: "Hello", + content: "Test", + postContent: "World!", + postElement: null), "" - } + }, + { + GetTagHelperOutput( + tagName: "custom", + attributes: new Dictionary(), + selfClosing: false, + preElement: "Before", + preContent: null, + content: null, + postContent: null, + postElement: null), + "Before" + }, + { + GetTagHelperOutput( + tagName: null, + attributes: new Dictionary(), + selfClosing: false, + preElement: "Before", + preContent: null, + content: null, + postContent: null, + postElement: null), + "Before" + }, + { + GetTagHelperOutput( + tagName: null, + attributes: new Dictionary { { "test", "testVal" } }, + selfClosing: true, + preElement: "Before", + preContent: null, + content: null, + postContent: null, + postElement: null), + "Before" + }, + { + GetTagHelperOutput( + tagName: "custom", + attributes: new Dictionary { { "test", "testVal" } }, + selfClosing: true, + preElement: "Before", + preContent: null, + content: null, + postContent: null, + postElement: null), + "Before" + }, + { + GetTagHelperOutput( + tagName: "custom", + attributes: new Dictionary(), + selfClosing: true, + preElement: "Before", + preContent: null, + content: null, + postContent: null, + postElement: null), + "Before" + }, + { + GetTagHelperOutput( + tagName: "custom", + attributes: new Dictionary(), + selfClosing: false, + preElement: null, + preContent: null, + content: null, + postContent: null, + postElement: "After"), + "After" + }, + { + GetTagHelperOutput( + tagName: null, + attributes: new Dictionary(), + selfClosing: false, + preElement: null, + preContent: null, + content: null, + postContent: null, + postElement: "After"), + "After" + }, + { + GetTagHelperOutput( + tagName: null, + attributes: new Dictionary { { "test", "testVal" } }, + selfClosing: true, + preElement: null, + preContent: null, + content: null, + postContent: null, + postElement: "After"), + "After" + }, + { + GetTagHelperOutput( + tagName: "custom", + attributes: new Dictionary { { "test", "testVal" } }, + selfClosing: true, + preElement: null, + preContent: null, + content: null, + postContent: null, + postElement: "After"), + "After" + }, + { + GetTagHelperOutput( + tagName: "custom", + attributes: new Dictionary(), + selfClosing: true, + preElement: null, + preContent: null, + content: null, + postContent: null, + postElement: "After"), + "After" + }, + { + GetTagHelperOutput( + tagName: "custom", + attributes: new Dictionary(), + selfClosing: false, + preElement: "Before", + preContent: "Hello", + content: "Test", + postContent: "World!", + postElement: "After"), + "BeforeHelloTestWorld!After" + }, + { + GetTagHelperOutput( + tagName: "custom", + attributes: new Dictionary { { "test", "testVal" } }, + selfClosing: false, + preElement: "Before", + preContent: "Hello", + content: "Test", + postContent: "World!", + postElement: "After"), + "BeforeHelloTestWorld!After" + }, + { + GetTagHelperOutput( + tagName: "custom", + attributes: new Dictionary(), + selfClosing: true, + preElement: "Before", + preContent: "Hello", + content: "Test", + postContent: "World!", + postElement: "After"), + "BeforeAfter" + }, + { + GetTagHelperOutput( + tagName: null, + attributes: new Dictionary(), + selfClosing: true, + preElement: "Before", + preContent: "Hello", + content: "Test", + postContent: "World!", + postElement: "After"), + "BeforeHelloTestWorld!After" + }, + { + GetTagHelperOutput( + tagName: null, + attributes: new Dictionary(), + selfClosing: false, + preElement: "Before", + preContent: "Hello", + content: "Test", + postContent: "World!", + postElement: "After"), + "BeforeHelloTestWorld!After" + }, + { + GetTagHelperOutput( + tagName: null, + attributes: new Dictionary { { "test", "testVal" } }, + selfClosing: false, + preElement: "Before", + preContent: "Hello", + content: "Test", + postContent: "World!", + postElement: "After"), + "BeforeHelloTestWorld!After" + }, }; } } @@ -937,18 +1217,22 @@ namespace Microsoft.AspNet.Mvc.Razor string tagName, IDictionary attributes, bool selfClosing, + string preElement, string preContent, string content, - string postContent) + string postContent, + string postElement) { var output = new TagHelperOutput(tagName, attributes) { SelfClosing = selfClosing }; + output.PreElement.SetContent(preElement); output.PreContent.SetContent(preContent); output.Content.SetContent(content); output.PostContent.SetContent(postContent); + output.PostElement.SetContent(postElement); return output; } diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/SurroundTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/SurroundTagHelper.cs new file mode 100644 index 0000000000..e8e3f26e0d --- /dev/null +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/SurroundTagHelper.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Razor.Runtime.TagHelpers; + +namespace TagHelpersWebSite.TagHelpers +{ + [TargetElement(Attributes = nameof(Surround))] + public class SurroundTagHelper : TagHelper + { + public override int Order + { + get + { + // Run first + return int.MinValue; + } + } + + public string Surround { get; set; } + + public override void Process(TagHelperContext context, TagHelperOutput output) + { + var surroundingTagName = Surround.ToLowerInvariant(); + + output.PreElement.SetContent($"<{surroundingTagName}>"); + output.PostElement.SetContent($""); + } + } +} \ No newline at end of file diff --git a/test/WebSites/TagHelpersWebSite/Views/Home/Index.cshtml b/test/WebSites/TagHelpersWebSite/Views/Home/Index.cshtml index 2be5cdc0e0..79fec8959f 100644 --- a/test/WebSites/TagHelpersWebSite/Views/Home/Index.cshtml +++ b/test/WebSites/TagHelpersWebSite/Views/Home/Index.cshtml @@ -17,16 +17,16 @@ }

-

This website has not been approved yet. Visit www.contoso.com for more information.

+

This website has not been approved yet. Visit www.contoso.com for more information.

Current Tag Cloud from Tag Helper

-
+

Current Tag Cloud from ViewComponentHelper:

@await Component.InvokeAsync("Tags", 15)
@section footerContent { -

© @Model.CopyrightYear - My ASP.NET Application

+

© @Model.CopyrightYear - My ASP.NET Application

} \ No newline at end of file