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, klientinitiering, dokumentöppning och körning.
Serverinställning
AddDoconut() registrerar tjänsterna; UseDoconutResources() och UseDoconut() kopplar middleware. Resurs‑anropet måste komma först. Session‑anropen krävs också — Doconut:s standarddokument‑sä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.
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:
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 bildresurs‑sökväg är därför ResPath: 'doconut-res/images'. Skriv båda utan inledande snedstreck: viewern lägger till ett själv, så '/doconut' skulle bli //doconut/DocImage.axd, vilket webbläsaren tolkar som en begäran till en värd som heter doconut, och viewern misslyckas med "Viewer‑hanteraren kunde inte nås".
Lägg till viewern på en sida
Viewer är den nödvändiga kärnan på sidan. Dess renderingsyta använder två nästlade divs:
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>Behandla verktygsfältet, modul‑monteringarna 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äster alltid på Viewer på samma sida. Använd samma ordning som
Doconut.TestApp och Doconut.TestApp.Distributed:
<nav id="toolbar" aria-label="Document viewer controls">
<!-- Viewer-navigering, zoom, sökning och annoteringsknappar -->
</nav>
<div id="searchBarMount"></div>
<div id="annBarMount"></div>
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>Referera till viewer‑resurserna
I en Razor‑vy, den injicerade Viewer‑tjänsten genererar viewer‑<link> och <script>‑taggar i beroendeordning — widgeten är ett jQuery‑plugin, så jQuery måste laddas innan viewer‑skripten:
@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.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ärn‑flaggorna. Publicera aldrig ett
Sök‑ eller Annotation‑Band‑exempel 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):
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 ribbon 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 versaliseringen fel så 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 6‑referensapplikationerna installerar följande delar tillsammans på en sida:
| Del av paketet | Krav | Hur det är anslutet |
|---|---|---|
Viewer‑resurser, montering och objViewer | Krävs | Kärndokumentrenderare |
| Viewer‑verktygsfält | Krävs i referenssammanställningen | Värdmarkering; knappar anropar samma objViewer |
| Sökband | Valfritt, licensierad modul | doconutSearchBar(...).attach(objViewer) |
| Annoteringsband | Valfritt, licensierad modul | doconutAnnotationBar(...).attach(objViewer) |
Även om huvud‑Viewer‑verktygsfältet är värdmarkering, installeras det tillsammans med Viewer och får aldrig dokumenteras som en fristående kontroll. Detta håller dess layout, etiketter, ikoner och auktoriseringsregler under din applikations kontroll medan varje knapp styr samma Viewer‑instans:
<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">‑markering tillsammans när du kopierar den fullständiga demoinställningen.
Behåll paketets initieringsordning som används av båda referensapplikationerna:
- Generera CSS för Viewer och licensierade moduler.
- Rendera Viewer‑verktygsfältet, Search/Annotation‑monteringar och Viewer‑montering tillsammans.
- Generera skript för Viewer och licensierade moduler.
- Ladda värdapplikationens
viewerToolbar.js. - Initiera
docVieweroch behåll den resulterandeobjViewer. - Initiera varje licensierad Search‑ eller Annotation‑Ribbon.
- Anropa
attach(objViewer)på varje Ribbon. - Öppna dokumentet och behåll dess token för Viewer‑ och modul‑förfrågningar.
Doconut.TestApp.Distributed behåller exakt denna UI‑sammansättning och samma Viewer‑verktygsfältshjälp. Dess extra access‑förfrågningsvärde och asynkrona render‑återförsöksinställningar tillhör den distribuerade transporten; de ändrar inte hur Viewer, verktygsfält eller Ribbons sätts ihop.
Server‑sidans skydd är viktiga: när en valfri funktionalitet är otillgänglig, genereras inte dess skript, så dess jQuery‑plugin‑funktion finns inte.
<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. Staplarna 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 endpoint: den injicerade Viewer‑tjänsten öppnar dokumentet och returnerar en sessionstoken.
app.MapPost("/api/open", async (Viewer viewer) =>
{
// Token är opak — ge den till widgeten, logga eller spara den aldrig.
string token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
return Results.Ok(new { token });
});Klienten hämtar token och överlämnar den till widgeten med objViewer.View(token):
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 färdiga begäransflödet är:
AddDoconut + middleware
-> render CSS/scripts and mount div
-> initialize docViewer
-> OpenDocumentAsync
-> return opaque token
-> objViewer.View(token)
-> page/search/annotation requests
-> Close / CloseDocumentBehandla token som en bärar‑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?