Hypertext Markup Language is the first programming language many of us learn. Like chess, it’s easy to learn but can take a lifetime to master. Its declarative syntax is ideal and ubiquitous across many different ecosystems, and C# embraces it with ASP.NET. In this post, we’ll investigateHtmlContentBuilder
, look at its API, and consider a potential DSL built on top of the builder.
What Is HtmlContentBuilder
Building HTML in code has always been tricky. How do we distinguish a tag from an intended literal? Improper handling of user input can lead to incorrect syntax, and at its worst, it could lead to security vulnerabilities. Let’s take a look at an example string.
Experienced developers will understand that we have a string value inside of an h1
tag. What about the following example?
The problem starts to get a little more difficult because in this case, everything inside of our code
tag should have been encoded.
ASP.NET has introduced a set of classes that allow us to work with HTML content in C#. These classes include HtmlContentBuilder
, HtmlString
, HtmlFormattableString
. All of them implement the IHtmlContent
interface. The most interesting class is HtmlContentBuilder
, which gives us the ability to work with HTML structures.
The HtmlContentBuilder
class allows us to Append
, Clear
, CopyTo
, MoveTo
, and WriteTo
efficiently.
Appending
HtmlContentBuilder
provides multiple Append
methods. They primarily differ in whether they encode the content passed into them.
It’s important to know that appending to the builder is not finalized immediately. Let’s take a look at the internal implementation of Append
.
HtmlContentBuilder stores values in an Entries
collection. Storage of entries will become clearer when we look at Move
and Copy
functions.
Usage of Append
methods is straightforward, with more fine-grained functionality coming in the form of extension methods found in HtmlContentBuilderExtensions
.
Moving Elements
Entries in an HtmlContentBuilder
instance need to be some flavor of IHtmlContent
. The storage of these entries allows us to move elements in and out of HTML containers.
Copying Elements
Copying is a necessary function for any templating approach. Looking at the implementation, we can see how a copy happens.
Using HtmlContentBuilder
For all intents and purposes, HtmlContentBuilder
is an internal implementation detail for ASP.NET MVC, Razor Pages, and Blazor. We likely will interact with HtmlString
more often than HtmlContentBuilder
. That doesn’t mean we are restricted to using this class in an ASP.NET application exclusively. Here is an example in a console application.
To get our results, we need a TextWriter
instance and the encoder for our HTML. Running the WriteTo
method, we see the expected output of HTML.
Not that exciting, but what we can do is wrap HTML elements in a custom domain-specific language (DSL). Here is the same output but with the HTML encapsulated in classes.
We get the same expected output.
Conclusion
Using the classes of HtmlContentBuilder
, HtmlString
, and HtmlFormattableString
give us the ability to build and manipulate HTML structures in C#. It’s important that these classes are meant to build new HTML structures, and cannot parse existing HTML. Leveraging these classes, we could build a custom DSL that lets us write HTML using C# syntax while getting all the benefits of encoding.
Please let me know what you think by leaving a comment below.