Ler o HTML do editor de texto rico no Blazor Server
Mais cedo ou mais tarde, uma página Blazor Server precisa levar o HTML do editor para o C# para salvá-lo. A chamada óbvia, JS.InvokeAsync<string>, funciona nos testes e falha no primeiro documento longo, porque o resultado trafega pela conexão SignalR do circuito, que tem um limite de 32 KB por mensagem. Esta página mostra o que aconteceu quando atingimos esse limite e como o exemplo lê o HTML como um stream.
O limite de 32 KB
No Blazor Server, toda mensagem do navegador para o servidor passa pelo circuito, e isso inclui o resultado de uma chamada de JS interop. O MaximumReceiveMessageSize do SignalR para o circuito é de 32 KB por padrão. Retornamos editor.getHTMLCode() por InvokeAsync<string> e medimos:
- 20,000 caracteres de HTML: chegaram.
- 40,000 caracteres: o navegador registrou "Connection disconnected with error 'Error: Server returned an error on close: Connection closed with an error.'" A mensagem na página não mudou, e o circuito tinha caído.
No nível de log padrão, a falha não aparece no servidor, por isso é fácil não notá-la nos testes.
Retorne bytes do JavaScript
Quando uma função JS retorna um Uint8Array, o Blazor pode entregá-lo ao .NET como um IJSStreamReference, que é enviado em partes, fora do limite de mensagem. As funções de interop do exemplo ficam em App.razor:
<script>
// Called from Home.razor. The editor options stay in JavaScript, where they can also hold
// functions (custom buttons, event handlers) that cannot be sent from .NET as JSON.
window.rteBlazor = {
create: function (host) {
host.rte = new RichTextEditor(host, {
toolbar: "full",
galleryEndpoint: "/rte/gallery",
maxUploadFileSize: 4000000 // same limit as the server, checked before the upload starts
});
},
// Returned as bytes: .NET reads them as a stream, so documents over Blazor's 32 KB
// SignalR message limit still arrive.
getHtml: function (host) {
return new TextEncoder().encode(host.rte.getHTMLCode());
},
destroy: function (host) {
if (!host || !host.rte) return;
// editor.destroy() exists only in newer editor builds
if (typeof host.rte.destroy === "function") host.rte.destroy();
host.rte = null;
host.innerHTML = "";
}
};
</script>getHtml codifica o HTML como UTF-8 com TextEncoder. O próprio editor é criado por create; Adicionar uma galeria de imagens a um editor de texto rico no Blazor explica create e destroy.
Leia o stream no C#
async Task Save()
{
var bytes = await JS.InvokeAsync<IJSStreamReference>("rteBlazor.getHtml", host);
await using var stream = await bytes.OpenReadStreamAsync(maxAllowedSize: 10_000_000);
using var reader = new StreamReader(stream);
var html = await reader.ReadToEndAsync();
message = $"Saved {html.Length} characters of HTML."; // save html to your database here
}InvokeAsync<IJSStreamReference>pede os bytes como um stream, e não como um valor.OpenReadStreamAsync(maxAllowedSize: 10_000_000)define o máximo que o servidor vai ler. O padrão é 512,000 bytes, então ajuste para o que a coluna do seu banco de dados comporta.StreamReadertransforma os bytes UTF-8 de volta em uma string. Salve a partir daqui, e sanitize o HTML antes de exibi-lo a outros usuários.
Com esse código, um documento com 100,000 caracteres x mais uma imagem inserida chegou completo: "Saved 100116 characters of HTML."
Por que não aumentar o limite
A outra saída é um MaximumReceiveMessageSize maior nas opções do hub, por exemplo com AddInteractiveServerComponents().AddHubOptions(...). Isso aumenta o limite para todas as mensagens de todos os circuitos. Não usamos nem testamos essa opção nesta página. O streaming mantém o padrão e só deixa passar o HTML, até o tamanho que você escolher.
Imagens são outro caso: elas nunca passam pelo componente. Enviar imagens de um editor de texto rico no Blazor explica por que o editor as envia para endpoints HTTP, de modo que o HTML salvo contém apenas as URLs delas.
Teste
Execute o projeto de exemplo deste guia com dotnet run e abra http://localhost:5304. Cole um documento longo no editor, ou digite alguns parágrafos e cole-os várias vezes, e clique em Save. A mensagem abaixo do editor mostra o número de caracteres que chegaram ao C#, bem acima de 32 KB. Para ver o limite, altere Save para ler o HTML com InvokeAsync<string> a partir de uma função JS que retorna getHTMLCode() como string, e salve o mesmo documento de novo: o circuito é fechado.