Merender HTML Mentah di Blazor dengan MarkupString
The other day I was building a component that needed to render some HTML that came from a CMS. I had the HTML string in a variable and just dropped it in the template like @myHtml. And of course, Blazor escaped everything and rendered the actual tags as text on the page. Not what I wanted.
The problem
By default, Blazor encodes any string you render in a template. So if you have:
@code {
private string content = "<strong>Hello</strong> <em>world</em>";
}
And you do this:
<div>@content</div>
You’ll see the literal text <strong>Hello</strong> <em>world</em> on the page instead of Hello world. Blazor does this on purpose to prevent XSS attacks, which is the right default behavior.
The solution: MarkupString
If you actually need to render raw HTML, you wrap your string in a MarkupString:
<div>@((MarkupString)content)</div>
And that’s it! Now Blazor will render the HTML as actual markup. You can also assign it to a variable:
@code {
private string rawHtml = "<strong>Hello</strong> <em>world</em>";
private MarkupString HtmlContent => (MarkupString)rawHtml;
}
<div>@HtmlContent</div>
A real world example
I was pulling blog content from an API and needed to render it in a preview component. The content had all sorts of HTML — headings, code blocks, links, images. Here’s roughly what it looked like:
@inject HttpClient Http
@if (article is not null)
{
<article>
<h1>@article.Title</h1>
<div class="content">
@((MarkupString)article.HtmlBody)
</div>
</article>
}
@code {
[Parameter]
public int ArticleId { get; set; }
private ArticleDto? article;
protected override async Task OnInitializedAsync()
{
article = await Http.GetFromJsonAsync<ArticleDto>($"api/articles/{ArticleId}");
}
}
Works perfectly. The HTML from the API gets rendered as actual markup.
Be careful with untrusted content
This is important: MarkupString does not sanitize the HTML. It renders whatever you give it, including <script> tags. So if the content comes from user input or an untrusted source, you need to sanitize it first.
There’s no built-in HTML sanitizer in Blazor, but you can use a library like HtmlSanitizer:
using Ganss.Xss;
@code {
private HtmlSanitizer sanitizer = new();
private MarkupString SafeHtml(string html)
{
var clean = sanitizer.Sanitize(html);
return (MarkupString)clean;
}
}
<div>@SafeHtml(untrustedContent)</div>
This strips out dangerous elements like <script>, onclick handlers, and other stuff you don’t want rendering from user-provided content.
When to use it
I use MarkupString for:
- CMS content or markdown that’s been converted to HTML server-side
- Rich text editor output
- Email templates preview
- Any pre-built HTML from trusted sources
For anything that comes from user input, always sanitize first. Better safe than sorry.
Hope you liked the post! Feel free to contact me on any social media at @emimontesdeoca.