Avvio Rapido

Visualizza il tuo primo documento in MVC 5 o Web Forms

Questo tutorial porta un'applicazione ASP.NET su .NET Framework 4.7.2 da un pacchetto installato a un documento visualizzato nel browser: Global.asax, un endpoint di apertura, le risorse del visualizzatore, il widget e il token che li collega. Presume che le registrazioni di Web.config da Installazione siano presenti — senza il gestore DocImage.axd e il modulo delle risorse, nulla di quanto segue può raggiungere il server.

Componi Doconut in Global.asax

Un Application_Start completo per un'applicazione 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 rende disponibili al processo le pagine di codice legacy utilizzate da alcuni formati di documento. Chiamalo una sola volta, prima che venga aperto il primo documento.
  • UnsafeMode = false è l'impostazione predefinita, scritta esplicitamente così che nessuno la modifichi per errore: DocImage.axd serve una pagina solo alla sessione ASP.NET che ha aperto il documento.
  • Le due chiamate IgnoreRoute tengono il routing MVC lontano da DocImage.axd e da /doconut-res/*, che sono serviti dal gestore e dal modulo. Un'applicazione Web Forms non ha rotte MVC e non necessita di queste righe.
  • DoconutHost.Shutdown interrompe il lavoro in background di Doconut e rilascia i suoi servizi quando il pool di applicazioni si ricicla. È sicuro chiamarlo anche se Initialize non è mai stato eseguito.

Apri un documento

Aprire un documento restituisce un token opaco. Il widget invia quel token con ogni richiesta di pagina.

In MVC 5, un'azione del controller risolve il servizio Viewer da DoconutHost.Services — MVC 5 non supporta l'iniezione tramite costruttore per questo servizio:

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 });
}

Il documento deve essere aperto all'interno di una richiesta che possiede lo stato di sessione, perché è l'apertura che concede alla sessione ASP.NET corrente l'accesso alle sue pagine. I controller MVC e le pagine Web Forms hanno lo stato di sessione per impostazione predefinita. Un IHttpHandler personalizzato non lo ha, a meno che non implementi System.Web.SessionState.IRequiresSessionState. Apri un documento da un handler senza tale supporto e il visualizzatore mostrerà "Non sei autorizzato a visualizzare questa pagina." su ogni pagina.

In Web Forms, la pagina stessa può aprire il documento nel suo code-behind. OpenDocument è la forma sincrona di OpenDocumentAsync, destinata al code-behind che non utilizza pagine asincrone:

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

Tratta il token come una credenziale di tipo bearer: non registrarlo né conservarlo; consegnalo solo al widget. Smette di funzionare quando la sessione del documento scade — apri nuovamente il documento per ottenerne uno nuovo.

Riferire le risorse del visualizzatore

Viewer.ReferenceCss e Viewer.ReferenceScripts generano i tag <link> e <script> per le risorse incorporate, nell'ordine di dipendenza, puntando a /doconut-res/. Il widget è un plugin jQuery, quindi jQuery viene prima.

MVC 5. Le viste non hanno @inject, quindi genera i tag nel controller e passali su 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)

Mantieni quel lavoro nel controller. MVC 5 compila le viste quando vengono servite per la prima volta e, senza un pacchetto compilatore aggiuntivo, quel compilatore comprende solo C# 5 — niente ?., niente $"...", niente nameof. Una vista che li utilizza compila correttamente in Visual Studio, poi restituisce un 500 vuoto nel browser.

Web Forms. Esporre le stesse stringhe dal code-behind e scriverle con <%= %>:

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

IncludeViewerCss e IncludeViewerScripts sono il nucleo obbligatorio. Per aggiungere i nastri di Ricerca e Annotazione, impostare anche IncludeSearchCss, IncludeAnnotationCss, IncludeSearchScripts, IncludeSearchBar, IncludeAnnotationScripts e IncludeAnnotationBar. Entrambi i metodi omettono i file di un nastro quando la licenza non concede tale capacità; il visualizzatore stesso si avvia comunque.

Aggiungere il visualizzatore a una pagina

La superficie di rendering è costituita da due div annidati:

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

Fornisci al div esterno un'altezza reale — il visualizzatore riempie il suo contenitore e lo misura quando si avvia. Il visualizzatore non disegna la propria barra degli strumenti: GotoPage, Next, Zoom, FitType e gli altri sono metodi che la tua pagina collega ai propri pulsanti, posizionati accanto al visualizzatore:

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>

Inizializzare il visualizzatore e mostrare il documento

Dopo gli script del visualizzatore, crea il widget, poi fornisci il token:

javascript
var objViewer = $('#div_ctlDoc').docViewer({
    showThumbs: true,
    autoLoad:   false,
    pageZoom:   100,
    FitType:    'width',
    BasePath:   '/',                   // '/' means DocImage.axd at the site root
    ResPath:    'doconut-res/images',  // no leading '/'
    onViewerReady: function () {
        // pages are visible; hide a loading indicator here
    },
    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); });

Nelle Web Forms, dove la pagina apre il documento da sola, le ultime tre righe diventano objViewer.View('<%= Token %>');.

Quattro dettagli qui falliscono senza un messaggio di errore:

  • BasePath: '/' indirizza DocImage.axd alla radice del sito. Per un'applicazione in una directory virtuale, usa il suo nome senza slash ('myapp' richiede /myapp/DocImage.axd). Uno slash iniziale ('/myapp') produce //myapp/DocImage.axd, che il browser interpreta come una richiesta a un altro host.
  • ResPath: 'doconut-res/images' — le icone si trovano una cartella sotto la radice delle risorse. Con 'doconut-res', ogni icona restituisce 404: nessuna icona della barra degli strumenti e nessuno spinner di caricamento, mentre il documento stesso viene comunque renderizzato. Uno slash iniziale lo rompe allo stesso modo di BasePath.
  • Le callback sono opzioni. onViewerReady, onError e le altre vanno nell'oggetto passato a docViewer(...). Una funzione globale nominata come il visualizzatore, ad esempio ctlDoc_ViewerReady, non viene mai chiamata.
  • Mantieni il visualizzatore, poi chiama View separatamente. docViewer(...) restituisce l'oggetto con Zoom, Next e FitType; View(...) restituisce qualcos'altro. var objViewer = $('#div_ctlDoc').docViewer({...}).View(token) renderizza il documento, poi fallisce con objViewer.Zoom is not a function al primo click sulla barra degli strumenti.

I nomi delle opzioni mescolano camelCase (showThumbs, autoLoad, pageZoom) e PascalCase (FitType, BasePath, ResPath). Un'opzione scritta in modo errato viene ignorata e il widget utilizza il valore predefinito.

L'alternativa a una riga

Per una pagina che deve solo mostrare un documento, senza una barra degli strumenti propria, Viewer.RenderViewer scrive l'intero script di inizializzazione — docViewer(...) con BasePath: '/' e ResPath: 'doconut-res/images', poi .View(token). Esiste solo in questo pacchetto:

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

Passa un ViewerConfig come terzo argomento per modificare lo zoom, l'adattamento o il pannello delle miniature. Poiché lo script generato non mantiene alcun riferimento al visualizzatore, utilizza l'inizializzazione scritta a mano sopra quando la tua pagina ha bisogno della propria barra degli strumenti.

Chiudi il documento

Chiama objViewer.Close(true) quando l'utente abbandona il visualizzatore o apre un sostituto: pulisce il widget e invia una richiesta di chiusura a DocImage.axd. objViewer.Close() senza argomento pulisce solo il widget. Sul server, viewer.CloseDocument(token) rimuove immediatamente la sessione del documento, rilascia le risorse di rendering e revoca l'accesso della sessione alle sue pagine. La scadenza scorrevole alla fine produce lo stesso effetto, ma chiudere esplicitamente i documenti di grandi dimensioni libera la memoria prima.

Esegui

Posiziona un PDF in ~/files/Sample.pdf, avvia il sito in IIS Express (F5 in Visual Studio) e apri la pagina che ospita il widget. La prima pagina viene renderizzata, con le miniature a sinistra. Se ciò non accade, consulta Risoluzione dei problemi.

Cosa ottieni senza licenza

Una licenza mancante non genera eccezioni. Il visualizzatore si rende normalmente, ma ogni pagina porta una filigrana di valutazione. Consulta Configurazione della licenza per sapere dove Doconut cerca la tua licenza.

Questa pagina è stata utile?