
Viewer é Stateless — Como Construir um Endpoint Aberto Minimal .NET 8
Viewer é Stateless — por Design
Viewer não mantém nenhum dado de documento por requisição. É uma classe selada, nunca implementa IDisposable, e cada documento que você abre vive em uma sessão separada que o cache do framework gerencia. Por isso você pode injetar uma única instância Viewer em qualquer lugar da sua aplicação ASP.NET Core e chamá‑la com segurança a partir de muitas requisições concorrentes.
Consequências de um serviço sem estado
- Nenhum recurso oculto – o próprio serviço nunca aloca buffers grandes que precisem de limpeza explícita.
- Thread‑safe por padrão – como nenhum estado específico de requisição é armazenado, a mesma instância
Viewerpode ser usada por múltiplas threads sem bloqueio. - Implantações escaláveis – o dimensionamento horizontal funciona pronto‑para‑uso; você não precisa de sessões persistentes ou afinidade de servidor, apenas do token de sessão que o cliente possui.
Todas as informações específicas do documento (páginas, anotações, índice de busca) são mantidas em uma sessão criada por OpenDocumentAsync. A sessão é armazenada em IMemoryCache (ou em qualquer IDistributedCache que você configure) e expira automaticamente após um período de inatividade (padrão 60 minutos). Quando terminar, você pode chamar CloseDocument para liberar a entrada do cache antecipadamente.
Registrando o Viewer sem estado
Porque Viewer não tem estado mutável, registre‑o uma única vez durante a inicialização:
builder.Services.AddDoconut(); // registra Viewer e middleware necessário
builder.Services.AddSession(); // necessário para a segurança do token
builder.Services.AddDistributedMemoryCache(); // cache simples para a demonstração
A chamada AddDoconut também conecta o middleware que serve os recursos estáticos do visualizador. Depois que os serviços estiverem configurados, você pode solicitar Viewer em qualquer assinatura de endpoint.
Endpoint minimalista de abertura de documento (exemplo net‑8)
O código a seguir é o trecho exato da documentação oficial e funciona pronto‑para‑uso em um projeto .NET 8 minimal‑API:
app.MapPost("/api/open", async (string fileName, Viewer viewer) =>
{
var token = await viewer.OpenDocumentAsync($"files/{fileName}");
return Results.Content(token, "text/plain");
});
O que o código faz
- Aceita um nome de arquivo – o cliente informa ao servidor qual arquivo em
wwwroot/filesabrir. - Chama
OpenDocumentAsync– oViewersem estado cria uma nova sessão, armazena‑a no cache e retorna um token opaco. - Retorna o token como texto simples – o cliente recebe apenas o token; o servidor nunca envia os bytes do documento nesta resposta.
Como Viewer não contém dados de documento, o endpoint não precisa de blocos using, chamadas Dispose ou fábricas por requisição. O token é a única credencial que o cliente enviará de volta ao widget do visualizador (objViewer.View(token) no front‑end).
Usando o token no lado do cliente
Depois que o token é retornado, o widget do front‑end chama objViewer.View(token). O widget então inclui o mesmo token em cada requisição subsequente para imagens de página, busca ou ações de anotação. O servidor valida o token contra a sessão que originalmente abriu o documento. Se o token for apresentado a partir de uma sessão de navegador diferente, o visualizador retorna um erro de autorização, que é o comportamento de segurança esperado.
Encerrando uma sessão antecipadamente (opcional)
Se o seu fluxo de trabalho souber que um documento nunca será acessado novamente, você pode liberar a entrada do cache invocando CloseDocument no Viewer. Isso remove a sessão do cache e impede que o temporizador de expiração deslizante a mantenha ativa.
Recapitulação do fluxo sem estado
| Etapa | O que acontece | Onde o estado reside |
|---|---|---|
| Injetar Viewer | Uma única instância Viewer é criada na inicialização. | No contêiner DI (singleton). |
| OpenDocumentAsync | Licença verificada → sessão criada → token retornado. | Sessão armazenada em IMemoryCache (ou cache distribuído). |
| Cliente renderiza | O widget envia o token em cada requisição. | O token é o único dado por documento que o cliente possui. |
| Expiração da sessão / CloseDocument | Entrada do cache removida após tempo limite ou fechamento explícito. | Nenhum recurso residual no serviço Viewer. |
Como o próprio serviço nunca armazena dados de documento, você pode escalar sua fazenda web com segurança, substituir nós ou reiniciar a aplicação sem perder nenhum estado visível ao usuário — apenas o token se torna inválido, fazendo o cliente reabrir o documento.
Implantando o Viewer sem estado na sua aplicação
- Adicione
AddDoconut,AddSessione um provedor de cache aoProgram.cs. - Cole o trecho do endpoint aberto na sua configuração minimal‑API.
- Passe o token retornado para
objViewer.View(token)no front‑end.
Agora você tem uma API de abertura de documento totalmente sem estado, pronta para produção, que aproveita o design Viewer da Doconut.