Making TagBuilder implement IHtmlContent and removing ToHtmlContent.

- Making TagRenderMode a property in TagBuilder.
- Modifying places where TagBuilder is used to suit the new model.
- This reduces space occupied by a normal application by 11.8%.
This commit is contained in:
sornaks 2015-08-10 17:14:19 -07:00
parent 93d07147b2
commit f2540f9ba1
13 changed files with 150 additions and 167 deletions

View File

@ -163,7 +163,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var antiforgeryTag = Generator.GenerateAntiforgery(ViewContext); var antiforgeryTag = Generator.GenerateAntiforgery(ViewContext);
if (antiforgeryTag != null) if (antiforgeryTag != null)
{ {
output.PostContent.Append(antiforgeryTag.ToString()); output.PostContent.Append(antiforgeryTag);
} }
} }
} }

View File

@ -236,13 +236,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
} }
} }
var tagBuilder = Generator.GenerateCheckBox( var checkBoxTag = Generator.GenerateCheckBox(
ViewContext, ViewContext,
modelExplorer, modelExplorer,
For.Name, For.Name,
isChecked: null, isChecked: null,
htmlAttributes: htmlAttributes); htmlAttributes: htmlAttributes);
if (tagBuilder != null) if (checkBoxTag != null)
{ {
// Do not generate current element's attributes or tags. Instead put both <input type="checkbox"/> and // Do not generate current element's attributes or tags. Instead put both <input type="checkbox"/> and
// <input type="hidden"/> into the output's Content. // <input type="hidden"/> into the output's Content.
@ -251,12 +251,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var renderingMode = var renderingMode =
output.TagMode == TagMode.SelfClosing ? TagRenderMode.SelfClosing : TagRenderMode.StartTag; output.TagMode == TagMode.SelfClosing ? TagRenderMode.SelfClosing : TagRenderMode.StartTag;
output.Content.Append(tagBuilder.ToHtmlContent(renderingMode)); checkBoxTag.TagRenderMode = renderingMode;
output.Content.Append(checkBoxTag);
tagBuilder = Generator.GenerateHiddenForCheckbox(ViewContext, modelExplorer, For.Name); var hiddenForCheckboxTag = Generator.GenerateHiddenForCheckbox(ViewContext, modelExplorer, For.Name);
if (tagBuilder != null) if (hiddenForCheckboxTag != null)
{ {
output.Content.Append(tagBuilder.ToHtmlContent(renderingMode)); hiddenForCheckboxTag.TagRenderMode = renderingMode;
output.Content.Append(hiddenForCheckboxTag);
} }
} }
} }

View File

@ -41,7 +41,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
inputTag.Attributes["checked"] = "checked"; inputTag.Attributes["checked"] = "checked";
} }
return inputTag.ToHtmlContent(TagRenderMode.SelfClosing); inputTag.TagRenderMode = TagRenderMode.SelfClosing;
return inputTag;
} }
private static IHtmlContent BooleanTemplateDropDownList(IHtmlHelper htmlHelper, bool? value) private static IHtmlContent BooleanTemplateDropDownList(IHtmlHelper htmlHelper, bool? value)
@ -52,17 +53,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
selectTag.Attributes["disabled"] = "disabled"; selectTag.Attributes["disabled"] = "disabled";
var content = new BufferedHtmlContent(); var content = new BufferedHtmlContent();
content.Append(selectTag.ToHtmlContent(TagRenderMode.StartTag));
foreach (var item in TriStateValues(value)) foreach (var item in TriStateValues(value))
{ {
content.Append( content.Append(DefaultHtmlGenerator.GenerateOption(item, item.Text));
DefaultHtmlGenerator.GenerateOption(item, item.Text)
.ToHtmlContent(TagRenderMode.Normal));
} }
content.Append(selectTag.ToHtmlContent(TagRenderMode.EndTag)); selectTag.InnerHtml = content;
return content; return selectTag;
} }
// Will soon need to be shared with the default editor templates implementations. // Will soon need to be shared with the default editor templates implementations.
@ -208,7 +205,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
var viewData = htmlHelper.ViewData; var viewData = htmlHelper.ViewData;
var templateInfo = viewData.TemplateInfo; var templateInfo = viewData.TemplateInfo;
var modelExplorer = viewData.ModelExplorer; var modelExplorer = viewData.ModelExplorer;
var content = new BufferedHtmlContent();
if (modelExplorer.Model == null) if (modelExplorer.Model == null)
{ {
@ -229,6 +225,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var serviceProvider = htmlHelper.ViewContext.HttpContext.RequestServices; var serviceProvider = htmlHelper.ViewContext.HttpContext.RequestServices;
var viewEngine = serviceProvider.GetRequiredService<ICompositeViewEngine>(); var viewEngine = serviceProvider.GetRequiredService<ICompositeViewEngine>();
var content = new BufferedHtmlContent();
foreach (var propertyExplorer in modelExplorer.Properties) foreach (var propertyExplorer in modelExplorer.Properties)
{ {
var propertyMetadata = propertyExplorer.Metadata; var propertyMetadata = propertyExplorer.Metadata;
@ -237,25 +234,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
continue; continue;
} }
var divTag = new TagBuilder("div");
if (!propertyMetadata.HideSurroundingHtml)
{
var label = propertyMetadata.GetDisplayName();
if (!string.IsNullOrEmpty(label))
{
divTag.SetInnerText(label);
divTag.AddCssClass("display-label");
content.AppendLine(divTag.ToHtmlContent(TagRenderMode.Normal));
// Reset divTag for reuse.
divTag.Attributes.Clear();
}
divTag.AddCssClass("display-field");
content.Append(divTag.ToHtmlContent(TagRenderMode.StartTag));
}
var templateBuilder = new TemplateBuilder( var templateBuilder = new TemplateBuilder(
viewEngine, viewEngine,
htmlHelper.ViewContext, htmlHelper.ViewContext,
@ -266,11 +244,26 @@ namespace Microsoft.AspNet.Mvc.Rendering
readOnly: true, readOnly: true,
additionalViewData: null); additionalViewData: null);
content.Append(templateBuilder.Build()); var templateBuilderResult = templateBuilder.Build();
if (!propertyMetadata.HideSurroundingHtml) if (!propertyMetadata.HideSurroundingHtml)
{ {
content.AppendLine(divTag.ToHtmlContent(TagRenderMode.EndTag)); var label = propertyMetadata.GetDisplayName();
if (!string.IsNullOrEmpty(label))
{
var labelTag = new TagBuilder("div");
labelTag.SetInnerText(label);
labelTag.AddCssClass("display-label");
content.AppendLine(labelTag);
}
var valueDivTag = new TagBuilder("div");
valueDivTag.AddCssClass("display-field");
valueDivTag.InnerHtml = templateBuilderResult;
content.AppendLine(valueDivTag);
}
else
{
content.Append(templateBuilderResult);
} }
} }
@ -312,8 +305,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var hyperlinkTag = new TagBuilder("a"); var hyperlinkTag = new TagBuilder("a");
hyperlinkTag.MergeAttribute("href", uriString); hyperlinkTag.MergeAttribute("href", uriString);
hyperlinkTag.SetInnerText(linkedText); hyperlinkTag.SetInnerText(linkedText);
return hyperlinkTag;
return hyperlinkTag.ToHtmlContent(TagRenderMode.Normal);
} }
} }
} }

View File

@ -256,28 +256,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
continue; continue;
} }
var divTag = new TagBuilder("div");
if (!propertyMetadata.HideSurroundingHtml)
{
var label = htmlHelper.Label(
propertyMetadata.PropertyName,
labelText: null,
htmlAttributes: null);
if (!string.IsNullOrEmpty(label.ToString()))
{
divTag.AddCssClass("editor-label");
divTag.InnerHtml = label; // already escaped
content.AppendLine(divTag.ToHtmlContent(TagRenderMode.Normal));
// Reset divTag for reuse.
divTag.Attributes.Clear();
}
divTag.AddCssClass("editor-field");
content.Append(divTag.ToHtmlContent(TagRenderMode.StartTag));
}
var templateBuilder = new TemplateBuilder( var templateBuilder = new TemplateBuilder(
viewEngine, viewEngine,
htmlHelper.ViewContext, htmlHelper.ViewContext,
@ -288,18 +266,36 @@ namespace Microsoft.AspNet.Mvc.Rendering
readOnly: false, readOnly: false,
additionalViewData: null); additionalViewData: null);
content.Append(templateBuilder.Build()); var templateBuilderResult = templateBuilder.Build();
if (!propertyMetadata.HideSurroundingHtml) if (!propertyMetadata.HideSurroundingHtml)
{ {
content.Append(" "); var label = htmlHelper.Label(propertyMetadata.PropertyName, labelText: null, htmlAttributes: null);
content.Append(htmlHelper.ValidationMessage( if (!string.IsNullOrEmpty(label.ToString()))
{
var labelTag = new TagBuilder("div");
labelTag.AddCssClass("editor-label");
labelTag.InnerHtml = label;
content.AppendLine(labelTag);
}
var valueDivTag = new TagBuilder("div");
valueDivTag.AddCssClass("editor-field");
var innerContent = new BufferedHtmlContent();
innerContent.Append(templateBuilderResult);
innerContent.Append(" ");
innerContent.Append(htmlHelper.ValidationMessage(
propertyMetadata.PropertyName, propertyMetadata.PropertyName,
message: null, message: null,
htmlAttributes: null, htmlAttributes: null,
tag: null)); tag: null));
valueDivTag.InnerHtml = innerContent;
content.AppendLine(divTag.ToHtmlContent(TagRenderMode.EndTag)); content.AppendLine(valueDivTag);
}
else
{
content.Append(templateBuilderResult);
} }
} }

View File

@ -157,6 +157,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var tagBuilder = new TagBuilder("input"); var tagBuilder = new TagBuilder("input");
tagBuilder.MergeAttribute("type", GetInputTypeString(InputType.Hidden)); tagBuilder.MergeAttribute("type", GetInputTypeString(InputType.Hidden));
tagBuilder.MergeAttribute("value", "false"); tagBuilder.MergeAttribute("value", "false");
tagBuilder.TagRenderMode = TagRenderMode.SelfClosing;
var fullName = GetFullHtmlFieldName(viewContext, expression); var fullName = GetFullHtmlFieldName(viewContext, expression);
tagBuilder.MergeAttribute("name", fullName); tagBuilder.MergeAttribute("name", fullName);
@ -673,7 +674,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
var messageTag = new TagBuilder(headerTag); var messageTag = new TagBuilder(headerTag);
messageTag.SetInnerText(message); messageTag.SetInnerText(message);
wrappedMessage.AppendLine(messageTag.ToHtmlContent(TagRenderMode.Normal)); wrappedMessage.AppendLine(messageTag);
} }
else else
{ {
@ -696,7 +697,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
{ {
var listItem = new TagBuilder("li"); var listItem = new TagBuilder("li");
listItem.SetInnerText(errorText); listItem.SetInnerText(errorText);
htmlSummary.AppendLine(listItem.ToHtmlContent(TagRenderMode.Normal)); htmlSummary.AppendLine(listItem);
isHtmlSummaryModified = true; isHtmlSummaryModified = true;
} }
} }
@ -726,7 +727,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var innerContent = new BufferedHtmlContent(); var innerContent = new BufferedHtmlContent();
innerContent.Append(wrappedMessage); innerContent.Append(wrappedMessage);
innerContent.Append(unorderedList.ToHtmlContent(TagRenderMode.Normal)); innerContent.Append(unorderedList);
tagBuilder.InnerHtml = innerContent; tagBuilder.InnerHtml = innerContent;
if (formContext != null && !excludePropertyErrors) if (formContext != null && !excludePropertyErrors)
@ -1015,6 +1016,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
var tagBuilder = new TagBuilder("input"); var tagBuilder = new TagBuilder("input");
tagBuilder.TagRenderMode = TagRenderMode.SelfClosing;
tagBuilder.MergeAttributes(htmlAttributes); tagBuilder.MergeAttributes(htmlAttributes);
tagBuilder.MergeAttribute("type", GetInputTypeString(inputType)); tagBuilder.MergeAttribute("type", GetInputTypeString(inputType));
tagBuilder.MergeAttribute("name", fullName, replaceExisting: true); tagBuilder.MergeAttribute("name", fullName, replaceExisting: true);
@ -1302,12 +1304,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
foreach (var group in groupedSelectList) foreach (var group in groupedSelectList)
{ {
var optGroup = group.First().Group; var optGroup = group.First().Group;
// Wrap if requested.
TagBuilder groupBuilder = null;
if (optGroup != null) if (optGroup != null)
{ {
groupBuilder = new TagBuilder("optgroup"); var groupBuilder = new TagBuilder("optgroup");
if (optGroup.Name != null) if (optGroup.Name != null)
{ {
groupBuilder.MergeAttribute("label", optGroup.Name); groupBuilder.MergeAttribute("label", optGroup.Name);
@ -1318,17 +1317,21 @@ namespace Microsoft.AspNet.Mvc.Rendering
groupBuilder.MergeAttribute("disabled", "disabled"); groupBuilder.MergeAttribute("disabled", "disabled");
} }
listItemBuilder.AppendLine(groupBuilder.ToHtmlContent(TagRenderMode.StartTag)); var optGroupContent = new BufferedHtmlContent().Append(Environment.NewLine);
} foreach (var item in group)
{
optGroupContent.AppendLine(GenerateOption(item));
}
foreach (var item in group) groupBuilder.InnerHtml = optGroupContent;
{ listItemBuilder.AppendLine(groupBuilder);
listItemBuilder.AppendLine(GenerateOption(item));
} }
else
if (optGroup != null)
{ {
listItemBuilder.AppendLine(groupBuilder.ToHtmlContent(TagRenderMode.EndTag)); foreach (var item in group)
{
listItemBuilder.AppendLine(GenerateOption(item));
}
} }
} }
@ -1338,7 +1341,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
private IHtmlContent GenerateOption(SelectListItem item) private IHtmlContent GenerateOption(SelectListItem item)
{ {
var tagBuilder = GenerateOption(item, item.Text); var tagBuilder = GenerateOption(item, item.Text);
return tagBuilder.ToHtmlContent(TagRenderMode.Normal); return tagBuilder;
} }
} }
} }

View File

@ -214,7 +214,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.Normal); return tagBuilder;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -542,7 +542,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.Normal); return tagBuilder;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -643,11 +643,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
var elements = new BufferedHtmlContent(); return new BufferedHtmlContent().Append(checkbox).Append(hidden);
elements.Append(checkbox.ToHtmlContent(TagRenderMode.SelfClosing));
elements.Append(hidden.ToHtmlContent(TagRenderMode.SelfClosing));
return elements;
} }
protected virtual string GenerateDisplayName([NotNull] ModelExplorer modelExplorer, string expression) protected virtual string GenerateDisplayName([NotNull] ModelExplorer modelExplorer, string expression)
@ -690,7 +686,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.Normal); return tagBuilder;
} }
protected virtual IHtmlContent GenerateEditor( protected virtual IHtmlContent GenerateEditor(
@ -751,7 +747,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
htmlAttributes); htmlAttributes);
if (tagBuilder != null) if (tagBuilder != null)
{ {
tagBuilder.ToHtmlContent(TagRenderMode.StartTag).WriteTo(ViewContext.Writer, _htmlEncoder); tagBuilder.TagRenderMode = TagRenderMode.StartTag;
tagBuilder.WriteTo(ViewContext.Writer, _htmlEncoder);
} }
return CreateForm(); return CreateForm();
@ -793,7 +790,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
htmlAttributes); htmlAttributes);
if (tagBuilder != null) if (tagBuilder != null)
{ {
tagBuilder.ToHtmlContent(TagRenderMode.StartTag).WriteTo(ViewContext.Writer, _htmlEncoder); tagBuilder.TagRenderMode = TagRenderMode.StartTag;
tagBuilder.WriteTo(ViewContext.Writer, _htmlEncoder);
} }
return CreateForm(); return CreateForm();
@ -819,7 +817,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.SelfClosing); return tagBuilder;
} }
protected virtual string GenerateId(string expression) protected virtual string GenerateId(string expression)
@ -847,7 +845,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.Normal); return tagBuilder;
} }
protected IHtmlContent GenerateListBox( protected IHtmlContent GenerateListBox(
@ -869,7 +867,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.Normal); return tagBuilder;
} }
protected virtual string GenerateName(string expression) protected virtual string GenerateName(string expression)
@ -895,7 +893,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.SelfClosing); return tagBuilder;
} }
protected virtual IHtmlContent GenerateRadioButton( protected virtual IHtmlContent GenerateRadioButton(
@ -917,7 +915,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.SelfClosing); return tagBuilder;
} }
protected virtual IHtmlContent GenerateTextArea( protected virtual IHtmlContent GenerateTextArea(
@ -939,7 +937,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.Normal); return tagBuilder;
} }
protected virtual IHtmlContent GenerateTextBox( protected virtual IHtmlContent GenerateTextBox(
@ -961,7 +959,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.SelfClosing); return tagBuilder;
} }
protected virtual IHtmlContent GenerateValidationMessage( protected virtual IHtmlContent GenerateValidationMessage(
@ -981,7 +979,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.Normal); return tagBuilder;
} }
protected virtual IHtmlContent GenerateValidationSummary( protected virtual IHtmlContent GenerateValidationSummary(
@ -1001,7 +999,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return HtmlString.Empty; return HtmlString.Empty;
} }
return tagBuilder.ToHtmlContent(TagRenderMode.Normal); return tagBuilder;
} }
protected virtual string GenerateValue(string expression, object value, string format, bool useViewData) protected virtual string GenerateValue(string expression, object value, string format, bool useViewData)

View File

@ -9,10 +9,11 @@ using System.Text;
using Microsoft.AspNet.Html.Abstractions; using Microsoft.AspNet.Html.Abstractions;
using Microsoft.AspNet.Mvc.ViewFeatures; using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc.Rendering namespace Microsoft.AspNet.Mvc.Rendering
{ {
public class TagBuilder public class TagBuilder : IHtmlContent
{ {
public TagBuilder(string tagName) public TagBuilder(string tagName)
{ {
@ -31,6 +32,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
public string TagName { get; private set; } public string TagName { get; private set; }
/// <summary>
/// The <see cref="Rendering.TagRenderMode"/> with which the tag is written.
/// </summary>
/// <remarks>Defaults to <see cref="TagRenderMode.Normal"/>.</remarks>
public TagRenderMode TagRenderMode { get; set; } = TagRenderMode.Normal;
public void AddCssClass(string value) public void AddCssClass(string value)
{ {
string currentValue; string currentValue;
@ -125,7 +132,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
} }
private void AppendAttributes(BufferedHtmlContent content) private void AppendAttributes(TextWriter writer, IHtmlEncoder encoder)
{ {
foreach (var attribute in Attributes) foreach (var attribute in Attributes)
{ {
@ -136,11 +143,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
continue; continue;
} }
content.Append(" "); writer.Write(" ");
content.Append(key); writer.Write(key);
content.Append("=\""); writer.Write("=\"");
content.Append(new StringHtmlContent(attribute.Value)); encoder.HtmlEncode(attribute.Value, writer);
content.Append("\""); writer.Write("\"");
} }
} }
@ -185,48 +192,39 @@ namespace Microsoft.AspNet.Mvc.Rendering
InnerHtml = new StringHtmlContent(innerText); InnerHtml = new StringHtmlContent(innerText);
} }
/// <summary> /// <inheritdoc />
/// Converts the <see cref="TagBuilder"/> to <see cref="IHtmlContent"/> with the specified public void WriteTo(TextWriter writer, IHtmlEncoder encoder)
/// <see cref="TagRenderMode"/>.
/// </summary>
/// <param name="renderMode"><see cref="TagRenderMode"/> with which the <see cref="TagBuilder"/>
/// should be written.</param>
/// <returns><see cref="IHtmlContent"/> containing the contents of the <see cref="TagBuilder"/>.</returns>
public IHtmlContent ToHtmlContent(TagRenderMode renderMode)
{ {
var content = new BufferedHtmlContent(); switch (TagRenderMode)
switch (renderMode)
{ {
case TagRenderMode.StartTag: case TagRenderMode.StartTag:
content.Append("<"); writer.Write("<");
content.Append(TagName); writer.Write(TagName);
AppendAttributes(content); AppendAttributes(writer, encoder);
content.Append(">"); writer.Write(">");
break; break;
case TagRenderMode.EndTag: case TagRenderMode.EndTag:
content.Append("</"); writer.Write("</");
content.Append(TagName); writer.Write(TagName);
content.Append(">"); writer.Write(">");
break; break;
case TagRenderMode.SelfClosing: case TagRenderMode.SelfClosing:
content.Append("<"); writer.Write("<");
content.Append(TagName); writer.Write(TagName);
AppendAttributes(content); AppendAttributes(writer, encoder);
content.Append(" />"); writer.Write(" />");
break; break;
default: default:
content.Append("<"); writer.Write("<");
content.Append(TagName); writer.Write(TagName);
AppendAttributes(content); AppendAttributes(writer, encoder);
content.Append(">"); writer.Write(">");
content.Append(InnerHtml); InnerHtml.WriteTo(writer, encoder);
content.Append("</"); writer.Write("</");
content.Append(TagName); writer.Write(TagName);
content.Append(">"); writer.Write(">");
break; break;
} }
return content;
} }
private static class Html401IdUtil private static class Html401IdUtil

View File

@ -9,8 +9,10 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http.Internal; using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Framework.WebEncoders.Testing;
using Moq; using Moq;
using Xunit; using Xunit;
@ -57,7 +59,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var viewContext = TestableHtmlGenerator.GetViewContext(model: null, var viewContext = TestableHtmlGenerator.GetViewContext(model: null,
htmlGenerator: htmlGenerator, htmlGenerator: htmlGenerator,
metadataProvider: metadataProvider); metadataProvider: metadataProvider);
var expectedPostContent = "Something" + htmlGenerator.GenerateAntiforgery(viewContext); var expectedPostContent = "Something" +
HtmlContentUtilities.HtmlContentToString(
htmlGenerator.GenerateAntiforgery(viewContext),
new NullTestEncoder());
var formTagHelper = new FormTagHelper(htmlGenerator) var formTagHelper = new FormTagHelper(htmlGenerator)
{ {
Action = "index", Action = "index",

View File

@ -282,6 +282,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "class", "form-control" }, { "class", "form-control" },
}, },
TagRenderMode = TagRenderMode.SelfClosing
}; };
htmlGenerator htmlGenerator
.Setup(mock => mock.GenerateCheckBox( .Setup(mock => mock.GenerateCheckBox(
@ -297,7 +298,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelper.ViewContext, tagHelper.ViewContext,
tagHelper.For.ModelExplorer, tagHelper.For.ModelExplorer,
tagHelper.For.Name)) tagHelper.For.Name))
.Returns(new TagBuilder("hidden")) .Returns(new TagBuilder("hidden") { TagRenderMode = TagRenderMode.SelfClosing })
.Verifiable(); .Verifiable();
// Act // Act

View File

@ -83,7 +83,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}, },
}; };
return tagBuilder.ToHtmlContent(TagRenderMode.SelfClosing); tagBuilder.TagRenderMode = TagRenderMode.SelfClosing;
return tagBuilder;
} }
protected override IDictionary<string, object> GetValidationAttributes( protected override IDictionary<string, object> GetValidationAttributes(

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.TestCommon; using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.Framework.WebEncoders.Testing; using Microsoft.Framework.WebEncoders.Testing;
@ -73,36 +74,22 @@ namespace Microsoft.AspNet.Mvc.Core.Rendering
[Theory] [Theory]
[MemberData(nameof(RenderingTestingData))] [MemberData(nameof(RenderingTestingData))]
public void ToString_IgnoresIdAttributeCase(TagRenderMode renderingMode, string expectedOutput) public void WriteTo_IgnoresIdAttributeCase(TagRenderMode renderingMode, string expectedOutput)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p");
// An empty value id attribute should not be rendered via ToString. // An empty value id attribute should not be rendered via ToString.
tagBuilder.Attributes.Add("ID", string.Empty); tagBuilder.Attributes.Add("ID", string.Empty);
tagBuilder.TagRenderMode = renderingMode;
// Act // Act
var value = tagBuilder.ToHtmlContent(renderingMode); using (var writer = new StringWriter())
{
tagBuilder.WriteTo(writer, new NullTestEncoder());
// Assert // Assert
Assert.Equal(expectedOutput, HtmlContentUtilities.HtmlContentToString(value, new NullTestEncoder())); Assert.Equal(expectedOutput, writer.ToString());
} }
[Theory]
[MemberData(nameof(RenderingTestingData))]
public void ToHtmlString_IgnoresIdAttributeCase(TagRenderMode renderingMode, string expectedOutput)
{
// Arrange
var tagBuilder = new TagBuilder("p");
// An empty value id attribute should not be rendered via ToHtmlString.
tagBuilder.Attributes.Add("ID", string.Empty);
// Act
var value = tagBuilder.ToHtmlContent(renderingMode);
// Assert
Assert.Equal(expectedOutput, HtmlContentUtilities.HtmlContentToString(value, new NullTestEncoder()));
} }
[Fact] [Fact]

View File

@ -30,7 +30,7 @@ namespace ActivatorWebSite.TagHelpers
var content = await context.GetChildContentAsync(); var content = await context.GetChildContentAsync();
output.Content.SetContent(HtmlHelper.Hidden(Name, content).ToString()); output.Content.SetContent(HtmlHelper.Hidden(Name, content));
} }
} }
} }

View File

@ -28,7 +28,7 @@ namespace ActivatorWebSite.TagHelpers
var builder = new TagBuilder("h2"); var builder = new TagBuilder("h2");
var title = ViewContext.ViewBag.Title; var title = ViewContext.ViewBag.Title;
builder.SetInnerText(title); builder.SetInnerText(title);
output.PreContent.SetContent(builder.ToHtmlContent(TagRenderMode.Normal)); output.PreContent.SetContent(builder);
} }
} }
} }