
Tutorial: Abrir Documentos com o Visualizador Doconut Injetado no .NET 8
Introdução
Exemplos mais antigos do Doconut podem construir Viewer diretamente com argumentos de cache, contexto HTTP e caminho da licença. Esse não é o modelo atual de integração do .NET 8. AddDoconut() registra Viewer com injeção de dependência, e os endpoints da aplicação recebem o serviço em vez de chamar um construtor.

Este tutorial segue o fluxo de requisição atual: registre serviços e middleware, emita os recursos incorporados do visualizador, abra um documento com OpenDocumentAsync, retorne um token de sessão opaco e passe esse token para o widget do navegador.
1. Instalar e registrar Doconut
Adicione o pacote .NET 8:
dotnet add package Doconut.NET8
Registre Doconut e os serviços de sessão do ASP.NET:
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.MiddlewarePath = "/doconut";
options.ResourcesPath = "/doconut-res";
options.UnsafeMode = false;
});
builder.Services.AddSession();
Conecte o middleware na ordem necessária. O middleware de recursos deve ser executado antes do middleware terminal de documento:
app.UseRouting();
app.UseSession();
app.UseDoconutResources();
app.Map("/doconut", branch => branch.UseDoconut());
MiddlewarePath coordena a configuração, mas não cria o ramo ASP.NET por si só. O caminho mapeado /doconut deve corresponder ao BasePath do widget.
2. Adicionar a superfície do visualizador e recursos
O visualizador de navegador Doconut é um plugin jQuery. Em uma página Razor, injete Viewer e solicite que ele emita as tags de recurso na ordem de dependência:
@inject Doconut.Viewer Viewer
@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
IncludeViewerCss = true
}))
@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
IncludeJQuery = true,
IncludeViewerScripts = true
}))
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>
Inicialize o widget com caminhos que correspondam ao registro no servidor:
const objViewer = $('#div_ctlDoc').docViewer({
showThumbs: true,
autoLoad: false,
pageZoom: 100,
FitType: 'width',
BasePath: '/doconut',
ResPath: '/doconut-res/images',
onError: function (message) {
console.error('Doconut viewer error:', message);
}
});
A capitalização das opções é significativa. Use os nomes mostrados pela versão instalada em vez de normalizá-los para um único estilo.
3. Injetar Viewer e abrir um documento
Viewer é registrado como um serviço transitório. Resolva-o por meio de injeção de endpoint, injeção de construtor ou a funcionalidade equivalente em sua aplicação ASP.NET Core.
app.MapPost("/api/open", async (
Viewer viewer,
CancellationToken ct) =>
{
string token = await viewer.OpenDocumentAsync(
"wwwroot/files/Sample.pdf",
ct: ct);
return Results.Ok(new { token });
});
Para um upload, forneça um stream e um FileInfo cuja extensão identifica o formato de origem:
app.MapPost("/api/open-upload", async (
IFormFile file,
Viewer viewer,
CancellationToken ct) =>
{
await using var stream = file.OpenReadStream();
string token = await viewer.OpenDocumentAsync(
stream,
new FileInfo(file.FileName),
ct: ct);
return Results.Ok(new { token });
});
Valide o tamanho do upload, a extensão e a autorização antes de abrir o conteúdo fornecido pelo usuário. Não converta o nome de arquivo enviado em um caminho de servidor.
4. Passar o token para o widget
Recupere o endpoint de abertura e passe o token retornado para objViewer.View:
fetch('/api/open', { method: 'POST' })
.then(response => {
if (!response.ok) throw new Error('The document could not be opened.');
return response.json();
})
.then(data => objViewer.View(data.token))
.catch(error => console.error(error));
Trate o token como credencial de portador para uma sessão de documento ao vivo:
- Não registre nem persista‑o.
- Retorne‑o apenas a um cliente autorizado.
- Não exponha o caminho do arquivo fonte.
- Reabra o documento quando a sessão expirar.
- Feche a sessão quando o documento não for mais necessário.
5. Encerrar sessões do lado do servidor deliberadamente
O código cliente pode chamar objViewer.Close() quando o usuário sai do visualizador. Fluxos de trabalho do servidor também podem revogar um token conhecido explicitamente:
app.MapPost("/api/close", (string token, Viewer viewer) =>
{
viewer.CloseDocument(token);
return Results.NoContent();
});
O fechamento explícito é especialmente útil para documentos grandes. A expiração da sessão permanece como solução de contingência, não como substituto para um gerenciamento previsível do ciclo de vida da aplicação.
6. Adicionar módulos opcionais somente após o núcleo funcionar
Busca e anotações são anexadas ao mesmo visualizador inicializado. Adicione seus CSS, scripts, montagens, verificações de licenciamento e callbacks de ciclo de vida somente após o fluxo base ser bem‑sucedido:
AddDoconut + session services
-> UseSession
-> UseDoconutResources
-> mapped UseDoconut branch
-> viewer resources and mount
-> initialize docViewer
-> OpenDocumentAsync
-> objViewer.View(token)
Essa ordem mantém falhas de renderização do núcleo separadas da configuração de módulos opcionais.
Erros comuns de migração
| Padrão antigo ou incorreto | Direção atual do .NET 8 |
|---|---|
new Viewer(cache, accessor, licensePath) | Injetar Viewer após AddDoconut() |
| Chamadas estáticas de carregamento de licença no código de requisição | Configurar entrada de licença em AddDoconut() |
Exemplos síncronos de OpenDocument(...) | Use OpenDocumentAsync(...) |
| Um CDN externo ou inventado do visualizador | Emitir recursos incorporados com ReferenceCss e ReferenceScripts |
Uma API genérica JavaScript init() | Inicializar $('#div_ctlDoc').docViewer(...) |
| Persistir o token do visualizador | Persistir seu ID de documento; trate o token como temporário |
Use a documentação do Doconut oficial e verifique os exemplos com a versão do pacote instalado antes de adaptá‑los ao código de produção.