Renderizando HTML bruto no Blazor com MarkupString
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.