Fix #3087 - use IHtmlContentBuilder in TagBuilder
Improves authoring experience when using TagBuilder by taking advantage of IHtmlContentBuilder an its extension methods. TagBuilder.InnerHtml is no longer settable.
This commit is contained in:
parent
d03a851ab3
commit
a707311d9e
|
|
@ -52,13 +52,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
selectTag.AddCssClass("tri-state");
|
||||
selectTag.Attributes["disabled"] = "disabled";
|
||||
|
||||
var content = new BufferedHtmlContent();
|
||||
foreach (var item in TriStateValues(value))
|
||||
{
|
||||
content.Append(DefaultHtmlGenerator.GenerateOption(item, item.Text));
|
||||
selectTag.InnerHtml.Append(DefaultHtmlGenerator.GenerateOption(item, item.Text));
|
||||
}
|
||||
|
||||
selectTag.InnerHtml = content;
|
||||
|
||||
return selectTag;
|
||||
}
|
||||
|
||||
|
|
@ -251,14 +249,14 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
if (!string.IsNullOrEmpty(label))
|
||||
{
|
||||
var labelTag = new TagBuilder("div");
|
||||
labelTag.SetInnerText(label);
|
||||
labelTag.InnerHtml.SetContent(label);
|
||||
labelTag.AddCssClass("display-label");
|
||||
content.AppendLine(labelTag);
|
||||
}
|
||||
|
||||
var valueDivTag = new TagBuilder("div");
|
||||
valueDivTag.AddCssClass("display-field");
|
||||
valueDivTag.InnerHtml = templateBuilderResult;
|
||||
valueDivTag.InnerHtml.SetContent(templateBuilderResult);
|
||||
content.AppendLine(valueDivTag);
|
||||
}
|
||||
else
|
||||
|
|
@ -304,7 +302,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
{
|
||||
var hyperlinkTag = new TagBuilder("a");
|
||||
hyperlinkTag.MergeAttribute("href", uriString);
|
||||
hyperlinkTag.SetInnerText(linkedText);
|
||||
hyperlinkTag.InnerHtml.SetContent(linkedText);
|
||||
return hyperlinkTag;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,22 +274,20 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
{
|
||||
var labelTag = new TagBuilder("div");
|
||||
labelTag.AddCssClass("editor-label");
|
||||
labelTag.InnerHtml = label;
|
||||
labelTag.InnerHtml.SetContent(label);
|
||||
content.AppendLine(labelTag);
|
||||
}
|
||||
|
||||
var valueDivTag = new TagBuilder("div");
|
||||
valueDivTag.AddCssClass("editor-field");
|
||||
|
||||
var innerContent = new BufferedHtmlContent();
|
||||
innerContent.Append(templateBuilderResult);
|
||||
innerContent.AppendEncoded(" ");
|
||||
innerContent.Append(htmlHelper.ValidationMessage(
|
||||
|
||||
valueDivTag.InnerHtml.Append(templateBuilderResult);
|
||||
valueDivTag.InnerHtml.AppendEncoded(" ");
|
||||
valueDivTag.InnerHtml.Append(htmlHelper.ValidationMessage(
|
||||
propertyMetadata.PropertyName,
|
||||
message: null,
|
||||
htmlAttributes: null,
|
||||
tag: null));
|
||||
valueDivTag.InnerHtml = innerContent;
|
||||
|
||||
content.AppendLine(valueDivTag);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
var idString =
|
||||
TagBuilder.CreateSanitizedId(GetFullHtmlFieldName(viewContext, expression), IdAttributeDotReplacement);
|
||||
tagBuilder.Attributes.Add("for", idString);
|
||||
tagBuilder.SetInnerText(resolvedLabelText);
|
||||
tagBuilder.InnerHtml.SetContent(resolvedLabelText);
|
||||
tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes), replaceExisting: true);
|
||||
|
||||
return tagBuilder;
|
||||
|
|
@ -440,10 +440,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
// Convert each ListItem to an <option> tag and wrap them with <optgroup> if requested.
|
||||
var listItemBuilder = GenerateGroupsAndOptions(optionLabel, selectList);
|
||||
|
||||
var tagBuilder = new TagBuilder("select")
|
||||
{
|
||||
InnerHtml = listItemBuilder
|
||||
};
|
||||
var tagBuilder = new TagBuilder("select");
|
||||
tagBuilder.InnerHtml.SetContent(listItemBuilder);
|
||||
tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes));
|
||||
tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */);
|
||||
tagBuilder.GenerateId(fullName, IdAttributeDotReplacement);
|
||||
|
|
@ -537,11 +535,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
}
|
||||
|
||||
// The first newline is always trimmed when a TextArea is rendered, so we add an extra one
|
||||
// in case the value being rendered is something like "\r\nHello".
|
||||
var innerContent = new BufferedHtmlContent();
|
||||
innerContent.Append(HtmlString.NewLine);
|
||||
innerContent.Append(value);
|
||||
tagBuilder.InnerHtml = innerContent;
|
||||
// in case the value being rendered is something like "\r\nHello"
|
||||
tagBuilder.InnerHtml.AppendLine();
|
||||
tagBuilder.InnerHtml.Append(value);
|
||||
|
||||
return tagBuilder;
|
||||
}
|
||||
|
|
@ -630,11 +626,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
tagBuilder.SetInnerText(message);
|
||||
tagBuilder.InnerHtml.SetContent(message);
|
||||
}
|
||||
else if (modelError != null)
|
||||
{
|
||||
tagBuilder.SetInnerText(ValidationHelpers.GetUserErrorMessageOrDefault(modelError, modelState));
|
||||
tagBuilder.InnerHtml.SetContent(
|
||||
ValidationHelpers.GetUserErrorMessageOrDefault(modelError, modelState));
|
||||
}
|
||||
|
||||
if (formContext != null)
|
||||
|
|
@ -672,7 +669,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
headerTag = viewContext.ValidationSummaryMessageElement;
|
||||
}
|
||||
var messageTag = new TagBuilder(headerTag);
|
||||
messageTag.SetInnerText(message);
|
||||
messageTag.InnerHtml.SetContent(message);
|
||||
wrappedMessage.AppendLine(messageTag);
|
||||
}
|
||||
else
|
||||
|
|
@ -682,10 +679,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
|
||||
// If excludePropertyErrors is true, describe any validation issue with the current model in a single item.
|
||||
// Otherwise, list individual property errors.
|
||||
var htmlSummary = new BufferedHtmlContent();
|
||||
var isHtmlSummaryModified = false;
|
||||
var modelStates = ValidationHelpers.GetModelStateList(viewContext.ViewData, excludePropertyErrors);
|
||||
|
||||
var htmlSummary = new TagBuilder("ul");
|
||||
foreach (var modelState in modelStates)
|
||||
{
|
||||
foreach (var modelError in modelState.Errors)
|
||||
|
|
@ -695,8 +692,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
if (!string.IsNullOrEmpty(errorText))
|
||||
{
|
||||
var listItem = new TagBuilder("li");
|
||||
listItem.SetInnerText(errorText);
|
||||
htmlSummary.AppendLine(listItem);
|
||||
listItem.InnerHtml.SetContent(errorText);
|
||||
htmlSummary.InnerHtml.AppendLine(listItem);
|
||||
isHtmlSummaryModified = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -704,15 +701,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
|
||||
if (!isHtmlSummaryModified)
|
||||
{
|
||||
htmlSummary.AppendEncoded(HiddenListItem);
|
||||
htmlSummary.Append(HtmlString.NewLine);
|
||||
htmlSummary.InnerHtml.AppendEncoded(HiddenListItem);
|
||||
htmlSummary.InnerHtml.AppendLine();
|
||||
}
|
||||
|
||||
var unorderedList = new TagBuilder("ul")
|
||||
{
|
||||
InnerHtml = htmlSummary
|
||||
};
|
||||
|
||||
var tagBuilder = new TagBuilder("div");
|
||||
tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes));
|
||||
|
||||
|
|
@ -724,11 +716,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
{
|
||||
tagBuilder.AddCssClass(HtmlHelper.ValidationSummaryCssClassName);
|
||||
}
|
||||
|
||||
var innerContent = new BufferedHtmlContent();
|
||||
innerContent.Append(wrappedMessage);
|
||||
innerContent.Append(unorderedList);
|
||||
tagBuilder.InnerHtml = innerContent;
|
||||
|
||||
tagBuilder.InnerHtml.Append(wrappedMessage);
|
||||
tagBuilder.InnerHtml.Append(htmlSummary);
|
||||
|
||||
if (formContext != null && !excludePropertyErrors)
|
||||
{
|
||||
|
|
@ -911,7 +901,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
internal static TagBuilder GenerateOption(SelectListItem item, string text)
|
||||
{
|
||||
var tagBuilder = new TagBuilder("option");
|
||||
tagBuilder.SetInnerText(text);
|
||||
tagBuilder.InnerHtml.SetContent(text);
|
||||
|
||||
if (item.Value != null)
|
||||
{
|
||||
|
|
@ -1117,10 +1107,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
[NotNull] string url,
|
||||
object htmlAttributes)
|
||||
{
|
||||
var tagBuilder = new TagBuilder("a")
|
||||
{
|
||||
InnerHtml = new StringHtmlContent(linkText),
|
||||
};
|
||||
var tagBuilder = new TagBuilder("a");
|
||||
tagBuilder.InnerHtml.SetContent(linkText);
|
||||
|
||||
tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes));
|
||||
tagBuilder.MergeAttribute("href", url);
|
||||
|
|
@ -1317,13 +1305,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
groupBuilder.MergeAttribute("disabled", "disabled");
|
||||
}
|
||||
|
||||
var optGroupContent = new BufferedHtmlContent().Append(HtmlString.NewLine);
|
||||
groupBuilder.InnerHtml.AppendLine();
|
||||
foreach (var item in group)
|
||||
{
|
||||
optGroupContent.AppendLine(GenerateOption(item));
|
||||
groupBuilder.InnerHtml.AppendLine(GenerateOption(item));
|
||||
}
|
||||
|
||||
groupBuilder.InnerHtml = optGroupContent;
|
||||
|
||||
listItemBuilder.AppendLine(groupBuilder);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -24,13 +24,18 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
|
||||
TagName = tagName;
|
||||
Attributes = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
InnerHtml = new BufferedHtmlContent();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> Attributes { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the set of attributes that will be written to the tag.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Attributes { get; }
|
||||
|
||||
public IHtmlContent InnerHtml { get; [param: NotNull] set; } = HtmlString.Empty;
|
||||
public IHtmlContentBuilder InnerHtml { get; }
|
||||
|
||||
public string TagName { get; private set; }
|
||||
public string TagName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Rendering.TagRenderMode"/> with which the tag is written.
|
||||
|
|
@ -187,11 +192,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
}
|
||||
}
|
||||
|
||||
public void SetInnerText(string innerText)
|
||||
{
|
||||
InnerHtml = new StringHtmlContent(innerText);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void WriteTo(TextWriter writer, IHtmlEncoder encoder)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Html.Abstractions;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Microsoft.AspNet.Mvc.Actions;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.WebEncoders.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -143,10 +143,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
string childContent, string outputContent, string expectedOutputContent)
|
||||
{
|
||||
// Arrange
|
||||
var tagBuilder = new TagBuilder("span2")
|
||||
{
|
||||
InnerHtml = new HtmlString("New HTML")
|
||||
};
|
||||
var tagBuilder = new TagBuilder("span2");
|
||||
tagBuilder.InnerHtml.SetContentEncoded("New HTML");
|
||||
tagBuilder.Attributes.Add("data-foo", "bar");
|
||||
tagBuilder.Attributes.Add("data-hello", "world");
|
||||
|
||||
|
|
@ -204,10 +202,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
string childContent, string expectedOutputContent)
|
||||
{
|
||||
// Arrange
|
||||
var tagBuilder = new TagBuilder("span2")
|
||||
{
|
||||
InnerHtml = new HtmlString("New HTML")
|
||||
};
|
||||
var tagBuilder = new TagBuilder("span2");
|
||||
tagBuilder.InnerHtml.SetContentEncoded("New HTML");
|
||||
tagBuilder.Attributes.Add("data-foo", "bar");
|
||||
tagBuilder.Attributes.Add("data-hello", "world");
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Html.Abstractions;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Microsoft.AspNet.Mvc.Actions;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
|
|
@ -13,7 +14,6 @@ using Microsoft.AspNet.Mvc.Rendering;
|
|||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Microsoft.Framework.WebEncoders;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -131,11 +131,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
public async Task ProcessAsync_MergesTagBuilderFromGenerateValidationSummary()
|
||||
{
|
||||
// Arrange
|
||||
var tagBuilder = new TagBuilder("span2")
|
||||
{
|
||||
InnerHtml = new HtmlString("New HTML")
|
||||
};
|
||||
|
||||
var tagBuilder = new TagBuilder("span2");
|
||||
tagBuilder.InnerHtml.SetContentEncoded("New HTML");
|
||||
tagBuilder.Attributes.Add("data-foo", "bar");
|
||||
tagBuilder.Attributes.Add("data-hello", "world");
|
||||
tagBuilder.Attributes.Add("anything", "something");
|
||||
|
|
@ -225,10 +222,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
public async Task ProcessAsync_GeneratesValidationSummaryWhenNotNone(ValidationSummary validationSummary)
|
||||
{
|
||||
// Arrange
|
||||
var tagBuilder = new TagBuilder("span2")
|
||||
{
|
||||
InnerHtml = new HtmlString("New HTML")
|
||||
};
|
||||
var tagBuilder = new TagBuilder("span2");
|
||||
tagBuilder.InnerHtml.SetContentEncoded("New HTML");
|
||||
|
||||
var generator = new Mock<IHtmlGenerator>();
|
||||
generator
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.AspNet.Html.Abstractions;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Mvc.TestCommon;
|
||||
using Microsoft.Framework.WebEncoders.Testing;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -92,21 +92,6 @@ namespace Microsoft.AspNet.Mvc.Core.Rendering
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetInnerText_HtmlEncodesValue()
|
||||
{
|
||||
// Arrange
|
||||
var tagBuilder = new TagBuilder("p");
|
||||
|
||||
// Act
|
||||
tagBuilder.SetInnerText("TestValue");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
"HtmlEncode[[TestValue]]",
|
||||
HtmlContentUtilities.HtmlContentToString(tagBuilder.InnerHtml));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("HelloWorld", "HelloWorld")]
|
||||
[InlineData("¡HelloWorld", "zHelloWorld")]
|
||||
|
|
@ -119,5 +104,23 @@ namespace Microsoft.AspNet.Mvc.Core.Rendering
|
|||
// Assert
|
||||
Assert.Equal(output, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WriteTo_IncludesInnerHtml()
|
||||
{
|
||||
// Arrange
|
||||
var tagBuilder = new TagBuilder("p");
|
||||
tagBuilder.InnerHtml.AppendEncoded("<span>Hello</span>");
|
||||
tagBuilder.InnerHtml.Append(", World!");
|
||||
|
||||
// Act
|
||||
using (var writer = new StringWriter())
|
||||
{
|
||||
tagBuilder.WriteTo(writer, new CommonTestEncoder());
|
||||
|
||||
// Assert
|
||||
Assert.Equal("<p><span>Hello</span>HtmlEncode[[, World!]]</p>", writer.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.Html.Abstractions;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||
|
|
@ -26,8 +27,8 @@ namespace ActivatorWebSite.TagHelpers
|
|||
(HtmlHelper as ICanHasViewContext)?.Contextualize(ViewContext);
|
||||
|
||||
var builder = new TagBuilder("h2");
|
||||
var title = ViewContext.ViewBag.Title;
|
||||
builder.SetInnerText(title);
|
||||
var title = (string)ViewContext.ViewBag.Title;
|
||||
builder.InnerHtml.SetContent(title);
|
||||
output.PreContent.SetContent(builder);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue