diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs index 24472fe115..64d71834e1 100644 --- a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHost.cs @@ -92,15 +92,13 @@ namespace Microsoft.AspNet.Mvc.Razor ScopeManagerBeginMethodName = nameof(TagHelperScopeManager.Begin), ScopeManagerEndMethodName = nameof(TagHelperScopeManager.End), - OutputGenerateStartTagMethodName = nameof(TagHelperOutput.GenerateStartTag), - OutputGenerateContentMethodName = nameof(TagHelperOutput.GenerateContent), - OutputGenerateEndTagMethodName = nameof(TagHelperOutput.GenerateEndTag), - // Can't use nameof because RazorPage is not accessible here. CreateTagHelperMethodName = "CreateTagHelper", StartTagHelperWritingScopeMethodName = "StartTagHelperWritingScope", EndTagHelperWritingScopeMethodName = "EndTagHelperWritingScope", - HtmlEncoderPropertyName = "HtmlEncoder", + + WriteTagHelperAsyncMethodName = "WriteTagHelperAsync", + WriteTagHelperToAsyncMethodName = "WriteTagHelperToAsync", }) { ResolveUrlMethodName = "Href", diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs index b332d106d0..59a0810fdd 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Security.Claims; @@ -250,25 +251,88 @@ namespace Microsoft.AspNet.Mvc.Razor } /// - /// Writes an to the . + /// Writes the content of a specified . /// - /// Contains the data to be written. - public void Write(ITextWriterCopyable copyableTextWriter) + /// The execution context containing the content. + /// + /// A that on completion writes the content. + /// + public async Task WriteTagHelperAsync([NotNull] TagHelperExecutionContext tagHelperExecutionContext) { - WriteTo(Output, copyableTextWriter); + await WriteTagHelperToAsync(Output, tagHelperExecutionContext); } /// - /// Writes an to the . + /// Writes the content of a specified to the specified + /// . /// - /// The to which the - /// is written. - /// Contains the data to be written. - public void WriteTo([NotNull] TextWriter writer, ITextWriterCopyable copyableTextWriter) + /// The instance to write to. + /// The execution context containing the content. + /// + /// A that on completion writes the content + /// to the . + /// + public async Task WriteTagHelperToAsync( + [NotNull] TextWriter writer, + [NotNull] TagHelperExecutionContext tagHelperExecutionContext) { - if (copyableTextWriter != null) + var tagHelperOutput = tagHelperExecutionContext.Output; + var isTagNameNullOrWhitespace = string.IsNullOrWhiteSpace(tagHelperOutput.TagName); + + if (!isTagNameNullOrWhitespace) { - copyableTextWriter.CopyTo(writer); + writer.Write('<'); + writer.Write(tagHelperOutput.TagName); + + foreach (var attribute in tagHelperOutput.Attributes) + { + var value = HtmlEncoder.HtmlEncode(attribute.Value); + writer.Write(' '); + writer.Write(attribute.Key); + writer.Write("=\""); + writer.Write(value); + writer.Write('"'); + } + + if (tagHelperOutput.SelfClosing) + { + writer.Write(" /"); + } + + writer.Write('>'); + } + + if (isTagNameNullOrWhitespace || !tagHelperOutput.SelfClosing) + { + WriteTagHelperContentTo(writer, tagHelperOutput.PreContent); + if (tagHelperOutput.IsContentModified) + { + WriteTagHelperContentTo(writer, tagHelperOutput.Content); + } + else if (tagHelperExecutionContext.ChildContentRetrieved) + { + var childContent = await tagHelperExecutionContext.GetChildContentAsync(); + WriteTagHelperContentTo(writer, childContent); + } + else + { + await tagHelperExecutionContext.ExecuteChildContentAsync(); + } + + WriteTagHelperContentTo(writer, tagHelperOutput.PostContent); + } + + if (!isTagNameNullOrWhitespace && !tagHelperOutput.SelfClosing) + { + writer.Write(string.Format(CultureInfo.InvariantCulture, "", tagHelperOutput.TagName)); + } + } + + private void WriteTagHelperContentTo(TextWriter writer, TagHelperContent content) + { + foreach (var entry in content) + { + writer.Write(entry); } } @@ -310,20 +374,7 @@ namespace Microsoft.AspNet.Mvc.Razor } else { - // This path is called when GetChildContentAsync() is called in tag helper - // and content is not set. - var tagHelperContent = value as TagHelperContent; - if (tagHelperContent != null) - { - foreach (var entry in tagHelperContent) - { - writer.Write(entry); - } - } - else - { - WriteTo(writer, value.ToString()); - } + WriteTo(writer, value.ToString()); } } } diff --git a/src/Microsoft.AspNet.Mvc.TagHelpers/OptionTagHelper.cs b/src/Microsoft.AspNet.Mvc.TagHelpers/OptionTagHelper.cs index aca4a87b85..10529cc6e8 100644 --- a/src/Microsoft.AspNet.Mvc.TagHelpers/OptionTagHelper.cs +++ b/src/Microsoft.AspNet.Mvc.TagHelpers/OptionTagHelper.cs @@ -85,7 +85,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Select this