Related to How to migrate usage of StringBuilder+TagBuilder for HTML rendering?
Last active
February 7, 2025 00:13
-
-
Save sandrock/a563db9f1b4e466c5d45b881a7a3f1d0 to your computer and use it in GitHub Desktop.
migrate usage of StringBuilder+TagBuilder for HTML rendering
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace AspNetCoreTests; | |
using Microsoft.AspNetCore.Html; | |
using Microsoft.AspNetCore.Mvc.Rendering; | |
using System; | |
using System.Text; | |
using System.Text.Encodings.Web; | |
public static class Extensions | |
{ | |
public static void AppendEx(this StringBuilder builder, IHtmlContent? content) | |
{ | |
if (content != null) | |
{ | |
using (var writer = new StringWriter(builder)) | |
{ | |
content.WriteTo(writer, HtmlEncoder.Default); | |
} | |
} | |
} | |
public static void AppendEx(this StringBuilder contents, IHtmlContentBuilder html) | |
{ | |
// why do we need to do that? my StringBuilder is no good enough? | |
using (var writer = new StringWriter(contents)) | |
{ | |
html.WriteTo(writer, HtmlEncoder.Default); | |
} | |
} | |
public static void AppendEx(this StringBuilder contents, TagBuilder tag) | |
{ | |
// why do we need to do that? my StringBuilder is no good enough? | |
using (var writer = new StringWriter(contents)) | |
{ | |
tag.WriteTo(writer, HtmlEncoder.Default); | |
} | |
} | |
public static void SetInnerText(this TagBuilder tag, string value) | |
{ | |
tag.InnerHtml.Append(value); | |
} | |
public static void Append(this StringWriter writer, IHtmlContent html) | |
{ | |
html.WriteTo(writer, HtmlEncoder.Default); | |
} | |
public static IHtmlContent ToString(this TagBuilder tag, TagRenderMode mode) | |
{ | |
if (mode == TagRenderMode.StartTag) | |
{ | |
return tag.RenderStartTag(); | |
} | |
else if (mode == TagRenderMode.EndTag) | |
{ | |
return tag.RenderEndTag(); | |
} | |
else | |
{ | |
throw new ArgumentException(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace UnitTests; | |
using AspNetCoreTests; | |
using Microsoft.AspNetCore.Html; | |
using Microsoft.AspNetCore.Mvc.Rendering; | |
using Microsoft.Extensions.Primitives; | |
using System.Text; | |
using System.Text.Encodings.Web; | |
public class TagBuilderHowTos | |
{ | |
#if NETFRAMEWORK || false | |
/// <summary> | |
/// The old way. | |
/// </summary> | |
[Fact] | |
public void Test0() | |
{ | |
var contents = new StringBuilder(); | |
var tag = new TagBuilder("div"); | |
tag.SetInnerText("hello"); | |
contents.Append(tag.ToString(TagRenderMode.StartTag)); | |
Assert.Equal("<div>", contents.ToString()); | |
contents.Append(tag.InnerHtml); | |
Assert.Equal("<div>hello", contents.ToString()); | |
contents.Append(tag.ToString(TagRenderMode.EndTag)); | |
Assert.Equal("<div>hello</div>", contents.ToString()); | |
var result = MvcHtmlString.Create(contents.ToString()); | |
Assert.Equal("<div>hello</div>", result.ToString()); | |
} | |
#endif | |
#if NETCOREAPP | |
/// <summary> | |
/// Set RenderMode and use extension methods. | |
/// </summary> | |
/// <remarks>So many StringWriters</remarks> | |
[Fact] | |
public void Test1() | |
{ | |
var contents = new StringBuilder(); | |
var tag = new TagBuilder("div"); | |
tag.InnerHtml.Append("hello"); | |
tag.TagRenderMode = TagRenderMode.StartTag; | |
contents.AppendEx(tag); | |
Assert.Equal("<div>", contents.ToString()); | |
contents.AppendEx(tag.InnerHtml); | |
Assert.Equal("<div>hello", contents.ToString()); | |
tag.TagRenderMode = TagRenderMode.EndTag; | |
contents.AppendEx(tag); | |
Assert.Equal("<div>hello</div>", contents.ToString()); | |
var result = new HtmlString(contents.ToString()); | |
Assert.Equal("<div>hello</div>", result.ToString()); | |
} | |
/// <summary> | |
/// Use Render methods and use extension methods. | |
/// </summary> | |
/// <remarks>So many StringWriters</remarks> | |
[Fact] | |
public void Test2() | |
{ | |
var contents = new StringBuilder(); | |
var tag = new TagBuilder("div"); | |
tag.InnerHtml.Append("hello"); | |
contents.AppendEx(tag.RenderStartTag()); | |
Assert.Equal("<div>", contents.ToString()); | |
contents.AppendEx(tag.RenderBody()); | |
Assert.Equal("<div>hello", contents.ToString()); | |
contents.AppendEx(tag.RenderEndTag()); | |
Assert.Equal("<div>hello</div>", contents.ToString()); | |
var result = new HtmlString(contents.ToString()); | |
Assert.Equal("<div>hello</div>", result.ToString()); | |
} | |
/// <summary> | |
/// Use StringWriter instead of StringBuilder. | |
/// </summary> | |
/// <remarks>No more StringBuilder</remarks> | |
[Fact] | |
public void Test3() | |
{ | |
var contents = new StringWriter(); | |
var tag = new TagBuilder("div"); | |
tag.InnerHtml.Append("hello"); | |
tag.RenderStartTag().WriteTo(contents, HtmlEncoder.Default); | |
Assert.Equal("<div>", contents.ToString()); | |
tag.RenderBody()?.WriteTo(contents, HtmlEncoder.Default); | |
Assert.Equal("<div>hello", contents.ToString()); | |
tag.RenderEndTag().WriteTo(contents, HtmlEncoder.Default); | |
Assert.Equal("<div>hello</div>", contents.ToString()); | |
var result = new HtmlString(contents.ToString()); | |
Assert.Equal("<div>hello</div>", result.ToString()); | |
} | |
/// <summary> | |
/// Minimal code changes: extension methods. | |
/// </summary> | |
[Fact] | |
public void Test4() | |
{ | |
var contents = new StringWriter(); // change this type | |
var tag = new TagBuilder("div"); | |
tag.SetInnerText("hello"); // 1 extension method | |
contents.Append(tag.ToString(TagRenderMode.StartTag)); // 2 extension methods | |
Assert.Equal("<div>", contents.ToString()); | |
contents.Append(tag.InnerHtml); // 1 extension method | |
Assert.Equal("<div>hello", contents.ToString()); | |
contents.Append(tag.ToString(TagRenderMode.EndTag)); // 2 extension methods | |
Assert.Equal("<div>hello</div>", contents.ToString()); | |
var result = new HtmlString(contents.ToString()); | |
Assert.Equal("<div>hello</div>", result.ToString()); | |
} | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment