Snabbstart

Rendera ditt första dokument på några minuter

Denna genomgång tar en ASP.NET Core-app från en tom Program.cs till ett dokument som renderas i webbläsaren: serverregistrering, det kompletta Viewer‑paketet (Viewer‑verktygsfält, Viewer‑montering och valfria sök‑/annotationsband), resursreferenser, klientinitialisering, dokumentöppning och körning.

Serverinställning

AddDoconut() registrerar tjänsterna; UseDoconutResources() och UseDoconut() kopplar middleware. Resursanropet måste komma först. Sessionsanropen krävs också — Doconut:s standarddokumentssäkerhet validerar varje sidförfrågan mot ASP.NET‑sessionsstatus. Sessionsstatus behöver en cache: AddDistributedMemoryCache() tillhandahåller en. En MVC‑ eller Razor‑Pages‑app registrerar den redan, men en minimal‑API‑app gör det inte, och utan den stannar appen vid start med Unable to resolve service for type 'IDistributedCache'. Har du redan registrerat Doconut under Installation? Hoppa vidare till nästa avsnitt.

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddDistributedMemoryCache(); // session state behöver en cache (MVC/Razor Pages lägger redan till en)
builder.Services.AddSession(); // Doconut-dokumentsäkerhet bygger på ASP.NET session state

app.UseSession();          // anropa UseSession() innan UseDoconut()
app.UseDoconutResources(); // måste registreras innan UseDoconut()
app.UseDoconut();

För en produktionsliknande sökvägslayout, mappa dokument‑middleware till en explicit gren och håll de fyra sökvägsinställningarna i linje:

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Doconut.Viewer.lic");
    options.MiddlewarePath = "/doconut";
    options.ResourcesPath = "/doconut-res";
    options.UnsafeMode = false;
});
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession();

app.UseRouting();
app.UseSession();
app.UseDoconutResources();
app.Map("/doconut", branch => branch.UseDoconut());

MiddlewarePath är ett koordineringsvärde; det mappar inte en ASP.NET Core‑gren i sig självt. I detta exempel mappar värden /doconut, så klienten använder BasePath: 'doconut'. ResourcesPath levererar det inbäddade paketet på /doconut-res, och widgetens bildresursväg är därför ResPath: 'doconut-res/images'. Skriv båda utan inledande snedstreck: visaren lägger till ett själv, så '/doconut' skulle bli //doconut/DocImage.axd, vilket webbläsaren tolkar som en förfrågan till en värd som heter doconut, och visaren misslyckas med "The viewer handler could not be reached".

Lägg till visaren på en sida

Viewer är den nödvändiga kärnan på sidan. Dess renderingsyta använder två nästlade divs:

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

Behandla verktygsfältet, modulmonteringarna och Viewer‑ytan som en enda sidkomposition. Sök och Annotation injicerar sina inbäddade band i valfria monteringar, men dessa moduler är aldrig fristående: de fästs alltid på Viewer på samma sida. Använd samma ordning som Doconut.TestApp och Doconut.TestApp.Distributed:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <!-- Viewer‑navigering, zoom, sök‑ och annoteringsknappar -->
</nav>

<div id="searchBarMount"></div>
<div id="annBarMount"></div>

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

Referera till visarens resurser

I en Razor‑vy avger den injicerade Viewer‑tjänsten visarens <link>‑ och <script>‑taggar i beroendeordning — widgeten är ett jQuery‑plugin, så jQuery måste laddas innan visarskriptet:

html
@inject Doconut.Viewer Viewer

@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
    IncludeBootstrapCss = true,
    IncludeViewerCss    = true
}))

@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery        = true,
    IncludeBootstrap     = true,
    IncludeViewerScripts = true
}))

För det kompletta Viewer‑paketet, begär Viewer‑ och modulresurserna tillsammans:

html
@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
    IncludeBootstrapCss  = true,
    IncludeViewerCss     = true,
    IncludeSearchCss     = true,
    IncludeAnnotationCss = true
}))

@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery             = true,
    IncludeBootstrap         = true,
    IncludeViewerScripts     = true,
    IncludeSearchScripts     = true,
    IncludeSearchBar         = true,
    IncludeAnnotationScripts = true,
    IncludeAnnotationBar     = true
}))

IncludeViewerCss och IncludeViewerScripts är de obligatoriska kärnflaggan. Publicera aldrig ett exempel på sök‑ eller annotationsband utan dem, Viewer‑monteringen och en docViewer‑instans. ReferenceCss och ReferenceScripts utelämnar ett valfritt moduls resurser när den aktuella licensen inte ger den möjligheten; kärn‑Viewer startar ändå.

Initiera visaren

Klient‑sidans widget är ett jQuery‑plugin. Detta är en minimal uppsättning faktiska initieringsalternativ (inte pseudokod):

javascript
let searchBar = null;
let annBar = null;

const objViewer = $('#div_ctlDoc').docViewer({
    showThumbs: true,
    autoLoad:   false,
    pageZoom:   100,
    FitType:    'width',
    BasePath:   'doconut',             // ingen inledande '/'
    ResPath:    'doconut-res/images',  // ingen inledande '/'
    onViewerReady: function () {
        // sidorna är synliga; säkert att dölja en laddningsindikator här
    },
    // Vidarebefordra annoteringslivscykelhändelser till den inbäddade ribbonen när den är närvarande.
    onAnnLoaded:    () => annBar?.handleAnnLoaded(),
    onAnnSaved:     () => annBar?.handleAnnSaved(),
    onAnnSaveError: () => annBar?.handleAnnSaveError(),
    onAnnClosed:    () => annBar?.handleAnnClosed(),
    onError: function (message) {
        console.error('Doconut viewer error:', message);
    }
});

Alternativens versalisering är faktiskt blandad — showThumbs, autoLoad och pageZoom är camelCase, men FitType, BasePath och ResPath är PascalCase. Det finns ingen konsekvent regel; om du får fel versalisering ignoreras alternativet tyst (widgeten återgår till sitt standardvärde istället för att kasta ett fel).

Sätt ihop det kompletta Viewer‑paketet

Båda .NET 8‑referensapplikationerna installerar följande delar tillsammans på en sida:

Del av paketetKravHur den är ansluten
Viewer‑resurser, montering och objViewerKrävsKärndokumentrenderare
Viewer‑verktygsfältKrävs i referenssammanställningenVärd‑markup; knappar anropar samma objViewer
Sök‑bandValfri, licensierad moduldoconutSearchBar(...).attach(objViewer)
Annoterings‑bandValfri, licensierad moduldoconutAnnotationBar(...).attach(objViewer)

Även om huvud‑Viewer‑verktygsfältet är värd‑markup, installeras det tillsammans med Viewer och får aldrig dokumenteras som en fristående kontroll. Detta håller dess layout, etiketter, ikoner och behörighetsregler under din applikations kontroll medan varje knapp styr samma Viewer‑instans:

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.GotoPage(objViewer.TotalPages())">Last</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>
    <button type="button" onclick="objViewer.FitType('height')">Fit height</button>
    <button type="button" id="openSearch">Search</button>
    <button type="button" id="openAnnotations">Annotations</button>
</nav>

Det fullständiga referensverktygsfältet kopierar också wwwroot/js/viewerToolbar.js till värdapplikationen för rotation, miniatyr, utskrift, helskärm, layout och knapp‑tillstånd‑hjälpare. Ladda den värdfilen efter Viewer.ReferenceScripts(...). Håll hjälpen och dess <nav id="toolbar">‑markup tillsammans när du kopierar den fullständiga demoinstallationen.

Behåll paketets initieringsordning som används av båda referensapplikationerna:

  1. Sänd Viewer-, Search- och Annotation‑resurser tillsammans.
  2. Rendera Viewer‑verktygsfältet, Ribbon‑monteringar och Viewer‑montering tillsammans.
  3. Initiera docViewer först.
  4. Skapa varje licensierad Ribbon och fäst den till samma objViewer.
  5. Öppna dokumentet och behåll dess token för modul‑förfrågningar.

Doconut.TestApp.Distributed behåller exakt detta UI‑sammansättning och samma Viewer‑verktygsfältshjälp. Dess ytterligare access‑förfrågningsvärde och asynkrona render‑retry‑inställningar tillhör den distribuerade transporten; de förändrar inte hur Viewer, verktygsfältet eller Ribbons sätts ihop.

Server‑sidans skydd är viktiga: när en valfri funktionalitet är otillgänglig, sänds dess skript inte, så dess jQuery‑plugin‑funktion existerar inte.

html
<script>
    let currentToken = '';

    const refitViewer = () =>
        requestAnimationFrame(() => objViewer.Refit());

    @if (Viewer.IsSearchEnabled)
    {
        <text>
    searchBar = $('#searchBarMount').doconutSearchBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onLayout: refitViewer
    });
    searchBar.attach(objViewer);
        </text>
    }

    @if (Viewer.IsAnnotationEnabled)
    {
        <text>
    annBar = $('#annBarMount').doconutAnnotationBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onLayout: refitViewer
    });
    annBar.attach(objViewer);
        </text>
    }

    document.getElementById('openSearch').addEventListener('click', () => {
        if (!searchBar) return;
        searchBar.isOpen() ? searchBar.close() : searchBar.open();
    });

    document.getElementById('openAnnotations').addEventListener('click', () => {
        if (!annBar) return;
        annBar.isOpen() ? annBar.close() : annBar.open();
    });
</script>

Båda inbäddade komponenterna genererar sin egen Ribbon‑DOM. Search innehåller grupperna Find, Options och Results. Annotation innehåller sina författarverktyg, stilkontroller, spara‑åtgärder och valfria export‑/bild‑åtgärder. Balkarna exponerar open(), close(), reset() och isOpen(); anropa alltid attach(objViewer) en gång efter att de skapats.

Exemplet ovan utelämnar valfria värd‑callback‑funktioner och Annotation‑export‑/bild‑slutpunkter för att hålla uppstarten minimal. Se Sök och Annotationer för den kompletta funktionsspecifika konfigurationen, eller Anpassade teman för att styla eller ersätta det värdeägda Viewer‑verktygsfältet.

Öppna ett dokument

Server‑sidan är en enda slutpunkt: den injicerade Viewer‑tjänsten öppnar dokumentet och returnerar en sessionstoken.

csharp
app.MapPost("/api/open", async (Viewer viewer) =>
{
    // Token är opak — ge den till widget, logga eller spara den aldrig.
    string token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
    return Results.Ok(new { token });
});

Klienten hämtar den token och överlämnar den till widgeten med objViewer.View(token):

javascript
fetch('/api/open', { method: 'POST' })
    .then(resp => resp.json())
    .then(data => {
        currentToken = data.token;
        objViewer.View(currentToken);
    });

Stäng dokumentet

Anropa objViewer.Close() när användaren lämnar visaren eller öppnar ett ersättningsdokument. Vid serverstyrda arbetsflöden tar viewer.CloseDocument(token) omedelbart bort den cachade sessionen, avvecklar renderingsmotorn, raderar dess säkerhetsmarkör och återkallar token. Glidande utgång utför så småningom samma städning, men explicit stängning rekommenderas för stora dokument.

Den fullständiga begäranflödet är:

text
AddDoconut + middleware
    -> render CSS/scripts and mount div
    -> initialize docViewer
    -> OpenDocumentAsync
    -> return opaque token
    -> objViewer.View(token)
    -> page/search/annotation requests
    -> Close / CloseDocument

Behandla token som en bärare‑behörighet: logga den aldrig, lagra den aldrig, överlämna den endast till widgeten. Den identifierar en aktiv dokumentsession på servern och slutar fungera när den sessionen löper ut — öppna dokumentet igen för att få en ny.

Kör det

Placera en PDF på wwwroot/files/Sample.pdf, kör dotnet run och öppna sidan som innehåller widgeten. Den första sidan renderas i visaren, med en miniatyrpanel till vänster. Om den inte gör det, se Felsökning.

Vad du får utan licens

En saknad licens kastar inte ett fel. Visaren renderar normalt, men varje sida har ett utvärderingsvattenstämpel. Se Licensinställning för hur Doconut hittar en licens och vad som förändras när den gör det.

Var den här sidan hjälpsam?