Renderizando HTML bruto no Blazor com MarkupString

· 3 min de leitura

Outro dia eu estava construindo um componente que precisava renderizar algum HTML vindo de um CMS. Eu tinha a string HTML em uma variável e simplesmente a coloquei no modelo como @myHtml. E, claro, o Blazor escapou de tudo e renderizou as tags reais como texto na página. Não é o que eu queria.

O problema

Por padrão, o Blazor codifica qualquer string renderizada em um modelo. Então, se você tiver:

@code {
    private string content = "<strong>Hello</strong> <em>world</em>";
}

E você faz isso:

<div>@content</div>

Você verá o texto literal <strong>Hello</strong> <em>world</em> na página em vez de Hello world. O Blazor faz isso propositalmente para evitar ataques XSS, que é o comportamento padrão correto.

A solução: MarkupString

Se você realmente precisa renderizar HTML bruto, coloque sua string em um MarkupString:

<div>@((MarkupString)content)</div>

E é isso! Agora o Blazor renderizará o HTML como marcação real. Você também pode atribuí-lo a uma variável:

@code {
    private string rawHtml = "<strong>Hello</strong> <em>world</em>";
    private MarkupString HtmlContent => (MarkupString)rawHtml;
}
<div>@HtmlContent</div>

Um exemplo do mundo real

Eu estava extraindo o conteúdo do blog de uma API e precisava renderizá-lo em um componente de visualização. O conteúdo tinha todo tipo de HTML – títulos, blocos de código, links, imagens. Aqui está aproximadamente o que parecia:

@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}");
    }
}

Funciona perfeitamente. O HTML da API é renderizado como marcação real.

Tenha cuidado com conteúdo não confiável

Isso é importante: MarkupString não limpa o HTML. Ele renderiza tudo o que você fornecer, incluindo tags <script>. Portanto, se o conteúdo vier da entrada do usuário ou de uma fonte não confiável, você precisará higienizá-lo primeiro.

Não há sanitizador de HTML integrado no Blazor, mas você pode usar uma biblioteca como 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>

Isso remove elementos perigosos como manipuladores <script>, onclick e outras coisas que você não deseja renderizar do conteúdo fornecido pelo usuário.

Quando usar

Eu uso MarkupString para:

  • Conteúdo CMS ou markdown que foi convertido para HTML no lado do servidor
  • Saída do editor de rich text
  • Visualização de modelos de e-mail
  • Qualquer HTML pré-construído de fontes confiáveis

Para qualquer coisa que venha da entrada do usuário, sempre higienize primeiro. Melhor prevenir do que remediar.

Espero que você tenha gostado da postagem! Sinta-se à vontade para entrar em contato comigo em qualquer mídia social em @emimontesdeoca.

Recursos