Démarrage rapide

Rendez votre premier document dans MVC 5 ou Web Forms

Ce guide prend une application ASP.NET sous .NET Framework 4.7.2, d'un package installé jusqu'à un document rendu dans le navigateur : Global.asax, un point d'accès d'ouverture, les ressources du visualiseur, le widget et le jeton qui les relie. Il suppose que les enregistrements Web.config provenant de Installation sont en place — sans le gestionnaire DocImage.axd et le module de ressources, rien ci‑dessous ne peut atteindre le serveur.

Composer Doconut dans Global.asax

Un Application_Start complet pour une application MVC 5 :

csharp
// Global.asax.cs - compose once per worker process, release on shutdown.
protected void Application_Start()
{
    Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

    Doconut.DoconutHost.Initialize(options =>
    {
        options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
        options.UnsafeMode  = false; // a page is served only to the session that opened the document
    });

    // MVC only: keep the two Doconut endpoints out of routing.
    RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    RouteTable.Routes.IgnoreRoute("doconut-res/{*pathInfo}");
}

protected void Application_End()
{
    Doconut.DoconutHost.Shutdown();
}
  • Encoding.RegisterProvider rend les pages de code héritées utilisées par certains formats de documents disponibles pour le processus. Appelez‑le une fois, avant l'ouverture du premier document.
  • UnsafeMode = false est la valeur par défaut, explicitée afin que personne ne la modifie par accident : DocImage.axd sert une page uniquement à la session ASP.NET qui a ouvert le document.
  • Les deux appels IgnoreRoute maintiennent le routage MVC à l'écart de DocImage.axd et de /doconut-res/*, qui sont servis par le gestionnaire et le module. Une application Web Forms n’a pas de routes MVC et n’a besoin d’aucune de ces lignes.
  • DoconutHost.Shutdown arrête le travail en arrière‑plan de Doconut et libère ses services lorsque le pool d’applications se recycle. Il est sûr de l’appeler même si Initialize n’a jamais été exécuté.

Ouvrir un document

L’ouverture d’un document renvoie un jeton opaque. Le widget envoie ce jeton avec chaque requête de page.

Dans MVC 5, une action de contrôleur résout le service Viewer depuis DoconutHost.Services — MVC 5 ne possède pas d’injection de constructeur pour celui‑ci :

csharp
// POST /Document/Open
[HttpPost]
public async Task<ActionResult> Open()
{
    var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();

    // The token is opaque - hand it to the viewer, never log or persist it.
    string token = await viewer.OpenDocumentAsync(Server.MapPath("~/files/Sample.pdf"));
    return Json(new { token });
}

Le document doit être ouvert dans une requête disposant d’un état de session, car son ouverture accorde à la session ASP.NET actuelle l’accès à ses pages. Les contrôleurs MVC et les pages Web Forms possèdent l’état de session par défaut. Un IHttpHandler personnalisé n’en possède pas, à moins d’implémenter System.Web.SessionState.IRequiresSessionState. Ouvrez un document depuis un gestionnaire sans cela, et le visualiseur affichera « You Are Not Authorized To View This Page. » sur chaque page.

Dans Web Forms, la page elle‑même peut ouvrir le document dans son code‑behind. OpenDocument est la forme synchrone de OpenDocumentAsync, destinée au code‑behind qui n’utilise pas de pages asynchrones :

csharp
// 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"));
}

Traitez le jeton comme une preuve d’identité : ne le consignez jamais et ne le persistez pas ; remettez‑le uniquement au widget. Il cesse de fonctionner lorsque la session du document expire — rouvrez le document pour en obtenir un nouveau.

Référencer les ressources du visualiseur

Viewer.ReferenceCss et Viewer.ReferenceScripts génèrent les balises <link> et <script> pour les ressources intégrées, dans l'ordre de dépendance, en pointant vers /doconut-res/. Le widget est un plugin jQuery, donc jQuery vient en premier.

MVC 5. Les vues n'ont pas de @inject, donc créez les balises dans le contrôleur et transmettez‑les via ViewBag :

csharp
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
@Html.Raw(ViewBag.ViewerCss)
...
@Html.Raw(ViewBag.ViewerScripts)

Conservez ce travail dans le contrôleur. MVC 5 compile les vues lorsqu'elles sont servies pour la première fois, et sans un package de compilation supplémentaire ce compilateur ne comprend que le C# 5 — pas de ?., pas de $"...", pas de nameof. Une vue qui les utilise compile correctement dans Visual Studio, puis renvoie un 500 vide dans le navigateur.

Web Forms. Exposez les mêmes chaînes depuis le code‑behind et écrivez‑les avec <%= %> :

html
<head>
    <%= ViewerCss %>
</head>
<body>
    ...
    <%= ViewerScripts %>
</body>

IncludeViewerCss et IncludeViewerScripts constituent le cœur obligatoire. Pour ajouter les rubans Recherche et Annotation, définissez également IncludeSearchCss, IncludeAnnotationCss, IncludeSearchScripts, IncludeSearchBar, IncludeAnnotationScripts et IncludeAnnotationBar. Les deux méthodes omettent les fichiers d'un ruban lorsque la licence ne le permet pas ; le visualiseur lui‑même démarre tout de même.

Ajouter le visualiseur à une page

La surface de rendu est constituée de deux div imbriqués :

html
<div id="divDocViewer">
    <div id="div_ctlDoc"></div>
</div>

Donnez au div externe une hauteur réelle — le visualiseur remplit son conteneur et le mesure au démarrage. Le visualiseur ne dessine pas sa propre barre d'outils : GotoPage, Next, Zoom, FitType et les autres sont des méthodes que votre page relie à ses propres boutons, placés à côté du visualiseur :

html
<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>

Initialiser le visualiseur et afficher le document

Après les scripts du visualiseur, créez le widget, puis transmettez‑lui le jeton :

javascript
var objViewer = $('#div_ctlDoc').docViewer({
    showThumbs: true,
    autoLoad:   false,
    pageZoom:   100,
    FitType:    'width',
    BasePath:   '/',                   // '/' signifie DocImage.axd à la racine du site
    ResPath:    'doconut-res/images',  // pas de '/' initial
    onViewerReady: function () {
        // les pages sont visibles ; masquez ici un indicateur de chargement
    },
    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); });

Dans Web Forms, où la page ouvre le document elle‑même, les trois dernières lignes deviennent objViewer.View('<%= Token %>');.

Quatre détails échouent ici sans message d'erreur :

  • BasePath: '/' pointe vers DocImage.axd à la racine du site. Pour une application dans un répertoire virtuel, utilisez son nom sans barres obliques ('myapp' génère /myapp/DocImage.axd). Une barre oblique initiale ('/myapp') produit //myapp/DocImage.axd, que le navigateur interprète comme une requête vers un autre hôte.
  • ResPath: 'doconut-res/images' — les icônes se trouvent un dossier sous la racine des ressources. Avec 'doconut-res', chaque icône renvoie 404 : pas de glyphes de barre d'outils et pas de spinner de chargement, tandis que le document lui‑-même s’affiche toujours. Une barre oblique initiale le casse de la même façon que BasePath.
  • Les rappels sont des options. onViewerReady, onError et les autres se placent dans l'objet passé à docViewer(...). Une fonction globale nommée d'après le visualiseur, comme ctlDoc_ViewerReady, n’est jamais appelée.
  • Conservez le visualiseur, puis appelez View séparément. docViewer(...) renvoie l'objet contenant Zoom, Next et FitType ; View(...) renvoie autre chose. var objViewer = $('#div_ctlDoc').docViewer({...}).View(token) rend le document, puis échoue avec objViewer.Zoom is not a function au premier clic sur la barre d'outils.

Les noms d'options mélangent camelCase (showThumbs, autoLoad, pageZoom) et PascalCase (FitType, BasePath, ResPath). Une option mal orthographiée est ignorée, et le widget utilise sa valeur par défaut.

L'alternative en une ligne

Pour une page qui doit seulement afficher un document, sans barre d'outils propre, Viewer.RenderViewer écrit le script d'initialisation complet — docViewer(...) avec BasePath: '/' et ResPath: 'doconut-res/images', puis .View(token). Il n'existe que dans ce package :

csharp
// Web Forms code-behind, after opening the document
ViewerInit = viewer.RenderViewer("div_ctlDoc", Token);
html
<div id="div_ctlDoc" style="height: 100vh"></div>
<%= ViewerScripts %>
<%= ViewerInit %>

Passez un ViewerConfig comme troisième argument pour modifier le zoom, l'ajustement ou le panneau des miniatures. Comme le script généré ne conserve aucune référence au visualiseur, utilisez l'initialisation écrite à la main ci‑dessus lorsque votre page a besoin de sa propre barre d'outils.

Fermer le document

Appelez objViewer.Close(true) lorsque l'utilisateur quitte le visualiseur ou ouvre un remplacement : cela vide le widget et envoie une requête de fermeture à DocImage.axd. objViewer.Close() sans argument ne vide que le widget. Sur le serveur, viewer.CloseDocument(token) supprime immédiatement la session du document, libère ses ressources de rendu et retire l'accès de la session à ses pages. L'expiration glissante finit par faire de même, mais fermer explicitement les gros documents libère la mémoire plus tôt.

Exécuter

Placez un PDF dans ~/files/Sample.pdf, lancez le site dans IIS Express (F5 dans Visual Studio), et ouvrez la page qui héberge le widget. La première page se rend, avec des miniatures à gauche. Si cela ne se produit pas, consultez Dépannage.

Ce que vous obtenez sans licence

Une licence manquante ne génère pas d'exception. Le visualiseur rend normalement, mais chaque page porte un filigrane d'évaluation. Consultez Configuration de licence pour savoir où Doconut recherche votre licence.

Cette page était-elle utile ?