Início Rápido
Renderize seu primeiro documento em MVC 5 ou Web Forms
Este tutorial leva uma aplicação ASP.NET no .NET Framework 4.7.2 de um pacote instalado a um documento renderizado no navegador: Global.asax, um endpoint de abertura, os recursos do visualizador, o widget e o token que os conecta. Assume‑se que os registros no Web.config de Instalação estejam em vigor — sem o handler DocImage.axd e o módulo de recursos, nada abaixo pode alcançar o servidor.
Compose Doconut no Global.asax
Um Application_Start completo para uma aplicação MVC 5:
// Global.asax.cs - compose uma vez por processo de trabalho, libere no desligamento.
protected void Application_Start()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Doconut.DoconutHost.Initialize(options =>
{
options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
options.UnsafeMode = false; // uma página é servida apenas para a sessão que abriu o documento
});
// Apenas MVC: mantenha os dois endpoints Doconut fora do roteamento.
RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteTable.Routes.IgnoreRoute("doconut-res/{*pathInfo}");
}
protected void Application_End()
{
Doconut.DoconutHost.Shutdown();
}Encoding.RegisterProvidertorna as páginas de código legadas que alguns formatos de documento utilizam disponíveis ao processo. Chame‑o uma vez, antes que o primeiro documento seja aberto.UnsafeMode = falseé o padrão, escrito explicitamente para que ninguém o altere acidentalmente:DocImage.axdserve uma página apenas para a sessão ASP.NET que abriu o documento.- As duas chamadas
IgnoreRoutemantêm o roteamento MVC afastado deDocImage.axde/doconut-res/*, que são servidos pelo handler e pelo módulo. Uma aplicação Web Forms não possui rotas MVC e não precisa de nenhuma dessas linhas. DoconutHost.Shutdowninterrompe o trabalho em segundo plano do Doconut e libera seus serviços quando o pool de aplicações é reciclado. É seguro chamar mesmo seInitializenunca foi executado.
Abra um documento
Abrir um documento retorna um token opaco. O widget envia esse token em cada solicitação de página.
No MVC 5, uma ação de controller resolve o serviço Viewer a partir de DoconutHost.Services — o MVC 5 não possui injeção de dependência via construtor para ele:
// POST /Document/Open
[HttpPost]
public async Task<ActionResult> Open()
{
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
// O token é opaco - entregue‑o ao visualizador, nunca registre ou persista‑o.
string token = await viewer.OpenDocumentAsync(Server.MapPath("~/files/Sample.pdf"));
return Json(new { token });
}O documento deve ser aberto dentro de uma requisição que possua estado de sessão, pois ao abri‑lo concede à sessão ASP.NET atual acesso às suas páginas. Controllers MVC e páginas Web Forms possuem estado de sessão por padrão. Um IHttpHandler personalizado não possui, a menos que implemente System.Web.SessionState.IRequiresSessionState. Abra um documento a partir de um handler sem isso, e o visualizador exibirá “Você não está autorizado a visualizar esta página.” em cada página.
No Web Forms, a própria página pode abrir o documento em seu code-behind. OpenDocument é a forma síncrona de OpenDocumentAsync, destinada a code-behind que não utiliza páginas assíncronas:
// Default.aspx.cs
protected string Token;
protected void Page_Load(object sender, EventArgs e)
{
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
Token = viewer.OpenDocument(Server.MapPath("~/files/Sample.pdf"));
}Trate o token como uma credencial de portador: nunca o registre ou persista; entregue‑o apenas ao widget. Ele deixa de funcionar quando a sessão do documento expira — abra o documento novamente para obter um novo.
Referencie os recursos do visualizador
Viewer.ReferenceCss e Viewer.ReferenceScripts emitem as tags <link> e <script> para os recursos incorporados, na ordem de dependência, apontando para /doconut-res/. O widget é um plugin jQuery, portanto o jQuery vem primeiro.
MVC 5. As visualizações não têm @inject, então produza as tags no controlador e passe‑as via ViewBag:
public ActionResult Index()
{
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
ViewBag.ViewerCss = viewer.ReferenceCss(new CssConfig
{
IncludeBootstrapCss = true,
IncludeViewerCss = true
});
ViewBag.ViewerScripts = viewer.ReferenceScripts(new ScriptConfig
{
IncludeJQuery = true,
IncludeBootstrap = true,
IncludeViewerScripts = true
});
return View();
}@Html.Raw(ViewBag.ViewerCss)
...
@Html.Raw(ViewBag.ViewerScripts)Mantenha esse trabalho no controlador. O MVC 5 compila as visualizações quando são servidas pela primeira vez e, sem um pacote de compilador extra, esse compilador entende apenas C# 5 — sem ?., sem $"...", sem nameof. Uma visualização que os utiliza compila corretamente no Visual Studio, mas devolve um 500 vazio no navegador.
Web Forms. Exponha as mesmas strings do code‑behind e escreva‑as com <%= %>:
<head>
<%= ViewerCss %>
</head>
<body>
...
<%= ViewerScripts %>
</body>IncludeViewerCss e IncludeViewerScripts são o núcleo obrigatório. Para adicionar as faixas de Busca e Anotação, também defina IncludeSearchCss, IncludeAnnotationCss, IncludeSearchScripts, IncludeSearchBar, IncludeAnnotationScripts e IncludeAnnotationBar. Ambos os métodos omitem os arquivos de uma faixa quando a licença não concede essa capacidade; o visualizador ainda inicia.
Adicione o visualizador a uma página
A superfície de renderização são dois divs aninhados:
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>Dê ao div externo uma altura real — o visualizador preenche seu contêiner e o mede ao iniciar. O visualizador não desenha sua própria barra de ferramentas: GotoPage, Next, Zoom, FitType e o restante são métodos que sua página conecta a seus próprios botões, posicionados ao lado do visualizador:
<nav id="toolbar" aria-label="Document viewer controls">
<button type="button" onclick="objViewer.GotoPage(1)">First</button>
<button type="button" onclick="objViewer.Next(false)">Previous</button>
<button type="button" onclick="objViewer.Next(true)">Next</button>
<button type="button" onclick="objViewer.Zoom(false)">Zoom out</button>
<button type="button" onclick="objViewer.Zoom(true)">Zoom in</button>
<button type="button" onclick="objViewer.FitType('width')">Fit width</button>
</nav>Inicialize o visualizador e mostre o documento
Depois dos scripts do visualizador, crie o widget e, em seguida, forneça‑le o token:
var objViewer = $('#div_ctlDoc').docViewer({
showThumbs: true,
autoLoad: false,
pageZoom: 100,
FitType: 'width',
BasePath: '/', // '/' significa DocImage.axd na raiz do site
ResPath: 'doconut-res/images', // sem '/' inicial
onViewerReady: function () {
// as páginas estão visíveis; oculte um indicador de carregamento aqui
},
onError: function (message) {
console.error('Doconut viewer error:', message);
}
});
fetch('/Document/Open', { method: 'POST' })
.then(function (resp) { return resp.json(); })
.then(function (data) { objViewer.View(data.token); });No Web Forms, onde a página abre o documento por conta própria, as três últimas linhas tornam‑se objViewer.View('<%= Token %>');.
Quatro detalhes aqui falham sem uma mensagem de erro:
BasePath: '/'aponta paraDocImage.axdna raiz do site. Para uma aplicação em um diretório virtual, use seu nome sem barras ('myapp'solicita/myapp/DocImage.axd). Uma barra inicial ('/myapp') produz//myapp/DocImage.axd, que o navegador interpreta como uma requisição para outro host.ResPath: 'doconut-res/images'— os ícones ficam uma pasta abaixo da raiz de recursos. Com'doconut-res', cada ícone retorna 404: sem glifos da barra de ferramentas e sem spinner de carregamento, embora o documento ainda seja renderizado. Uma barra inicial o quebra da mesma forma queBasePath.- Callbacks são opções.
onViewerReady,onErrore os demais vão no objeto passado paradocViewer(...). Uma função global nomeada após o visualizador, comoctlDoc_ViewerReady, nunca é chamada. - Mantenha o visualizador, então chame
Viewseparadamente.docViewer(...)devolve o objeto comZoom,NexteFitType;View(...)devolve outra coisa.var objViewer = $('#div_ctlDoc').docViewer({...}).View(token)renderiza o documento, mas falha comobjViewer.Zoom is not a functionno primeiro clique da barra de ferramentas.
Os nomes das opções misturam camelCase (showThumbs, autoLoad, pageZoom) e PascalCase (FitType, BasePath, ResPath). Uma opção escrita incorretamente é ignorada, e o widget usa o padrão.
A alternativa de uma linha
Para uma página que só precisa exibir um documento, sem uma barra de ferramentas própria, Viewer.RenderViewer gera todo o script de inicialização — docViewer(...) com BasePath: '/' e ResPath: 'doconut-res/images', então .View(token). Ele existe apenas neste pacote:
// Código-behind do Web Forms, após abrir o documento
ViewerInit = viewer.RenderViewer("div_ctlDoc", Token);<div id="div_ctlDoc" style="height: 100vh"></div>
<%= ViewerScripts %>
<%= ViewerInit %>Passe um ViewerConfig como terceiro argumento para alterar o zoom, o ajuste ou o painel de miniaturas. Como o script gerado não mantém referência ao visualizador, use a inicialização escrita à mão acima quando sua página precisar de sua própria barra de ferramentas.
Fechar o documento
Chame objViewer.Close(true) quando o usuário sair do visualizador ou abrir um substituto: ele limpa o widget e envia uma solicitação de fechamento para DocImage.axd. objViewer.Close() sem argumento limpa apenas o widget. No servidor, viewer.CloseDocument(token) remove a sessão do documento imediatamente, libera seus recursos de renderização e revoga o acesso da sessão às suas páginas. A expiração deslizante acaba fazendo o mesmo, mas fechar documentos grandes explicitamente libera memória mais cedo.
Executar
Coloque um PDF em ~/files/Sample.pdf, inicie o site no IIS Express (F5 no Visual Studio) e abra a página que hospeda o widget. A primeira página é renderizada, com miniaturas à esquerda. Se não acontecer, veja Solução de Problemas.
O que você obtém sem licença
A falta de licença não gera erro. O visualizador renderiza normalmente, mas cada página exibe uma marca d'água de avaliação. Veja Configuração de Licença para saber onde o Doconut procura sua licença.
Esta página foi útil?