Skip to content

Instantly share code, notes, and snippets.

@sandrock
Last active March 21, 2023 10:53
Show Gist options
  • Save sandrock/a563db9f1b4e466c5d45b881a7a3f1d0 to your computer and use it in GitHub Desktop.
Save sandrock/a563db9f1b4e466c5d45b881a7a3f1d0 to your computer and use it in GitHub Desktop.
migrate usage of StringBuilder+TagBuilder for HTML rendering
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();
}
}
}
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