クイックスタート
数分で最初のドキュメントをレンダリング
このハウツーでは、空の Program.cs から始める ASP.NET Core アプリを、ブラウザーでドキュメントが表示されるまで導きます。サーバー登録、完全な Viewer パッケージ(Viewer ツールバー、Viewer マウント、オプションの検索/注釈リボン)、アセット参照、クライアント初期化、ドキュメントのオープン、そして実行です。
サーバー設定
AddDoconut() はサービスを登録します。UseDoconutResources() と UseDoconut() はミドルウェアを接続します。リソース呼び出しは最初に行う必要があります。セッション呼び出しも必須です — Doconut のデフォルトドキュメントセキュリティは、すべてのページリクエストを ASP.NET セッション状態と照合して検証します。すでに インストール 時に Doconut を登録しましたか?次のセクションへ進んでください。
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddSession(); // Doconut document security rides on ASP.NET session state
app.UseSession(); // call UseSession() before UseDoconut()
app.UseDoconutResources(); // must be registered before UseDoconut()
app.UseDoconut();プロダクション向けのパスレイアウトの場合、ドキュメントミドルウェアを明示的なブランチにマップし、4 つのパス設定を揃えておきます:
builder.Services.AddDoconut(options =>
{
options.LicensePath = Path.Combine(AppContext.BaseDirectory, "Doconut.Viewer.lic");
options.MiddlewarePath = "/doconut";
options.ResourcesPath = "/doconut-res";
options.UnsafeMode = false;
});
builder.Services.AddSession();
app.UseRouting();
app.UseSession();
app.UseDoconutResources();
app.Map("/doconut", branch => branch.UseDoconut());MiddlewarePath は調整用の値であり、単体で ASP.NET Core のブランチをマップするものではありません。この例ではホストが /doconut にマップしているため、クライアントは BasePath: '/doconut' を使用する必要があります。ResourcesPath は埋め込みバンドルを /doconut-res で提供し、ウィジェットの画像リソースパスはそのため ResPath: '/doconut-res/images' となります。
ページにビューアを追加
Viewer はページに必須のコアです。その描画領域は 2 つの入れ子になった div を使用します:
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>ツールバー、モジュールマウント、Viewer の表面を 1 つのページ構成として扱います。Search と Annotation は埋め込みリボンをオプションのマウントに注入しますが、これらのモジュールは単体で使用されることはなく、常に同じページの Viewer に添付されます。Doconut.TestApp と Doconut.TestApp.Distributed と同じ順序で使用してください:
<nav id="toolbar" aria-label="Document viewer controls">
<!-- Viewer navigation, zoom, Search, and Annotation buttons -->
</nav>
<div id="searchBarMount"></div>
<div id="annBarMount"></div>
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>ビューア資産を参照
Razor ビューでは、注入された Viewer サービスが依存順序でビューアの <link> と <script> タグを出力します — ウィジェットは jQuery プラグインであるため、viewer スクリプトの前に jQuery を読み込む必要があります:
@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
}))完全な Viewer パッケージを取得するには、Viewer とモジュールのリソースを一緒にリクエストします:
@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 と IncludeViewerScripts は必須のコアフラグです。これら、Viewer マウント、そして docViewer インスタンスなしで Search や Annotation リボンの例を公開しないでください。ReferenceCss と ReferenceScripts は、現在のライセンスがその機能を許可していない場合、オプションモジュールのリソースを省略しますが、コア Viewer は起動します。
ビューアを初期化
クライアント側ウィジェットは jQuery プラグインです。以下は実際の初期化オプションの最小セットです(疑似コードではありません):
let searchBar = null;
let annBar = null;
const objViewer = $('#div_ctlDoc').docViewer({
showThumbs: true,
autoLoad: false,
pageZoom: 100,
FitType: 'width',
BasePath: '/doconut',
ResPath: '/doconut-res/images',
onViewerReady: function () {
// pages are visible; safe to hide a loading spinner here
},
// Forward annotation lifecycle events to the embedded ribbon when it is present.
onAnnLoaded: () => annBar?.handleAnnLoaded(),
onAnnSaved: () => annBar?.handleAnnSaved(),
onAnnSaveError: () => annBar?.handleAnnSaveError(),
onAnnClosed: () => annBar?.handleAnnClosed(),
onError: function (message) {
console.error('Doconut viewer error:', message);
}
});オプションのケースは実際に混在しています — showThumbs、autoLoad、pageZoom は camelCase、FitType、BasePath、ResPath は PascalCase です。一貫したルールはなく、ケースが間違っているとオプションは黙って無視され(ウィジェットは例外を投げずにデフォルトにフォールバックします)。
完全な Viewer パッケージを組み立てる
.NET 8 のリファレンスアプリケーションは、以下のパーツを 1 ページにまとめてインストールします:
| パッケージの部分 | 要件 | 接続方法 |
|---|---|---|
Viewer リソース、マウント、そして objViewer | 必須 | コアドキュメントレンダラー |
| Viewer ツールバー | 参照構成で必須 | ホストマークアップ;ボタンは同じ objViewer を呼び出す |
| 検索リボン | オプション、ライセンス済みモジュール | doconutSearchBar(...).attach(objViewer) |
| 注釈リボン | オプション、ライセンス済みモジュール | doconutAnnotationBar(...).attach(objViewer) |
メインの Viewer ツールバーはホストのマークアップですが、Viewer と一緒にインストールされ、単独のコントロールとして文書化してはいけません。これにより、レイアウト、ラベル、アイコン、認可ルールがアプリケーション側で管理され、すべてのボタンが同じ Viewer インスタンスを操作します:
<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>完全なリファレンスツールバーは、回転、サムネイル、印刷、全画面、レイアウト、ボタン状態ヘルパー用に wwwroot/js/viewerToolbar.js をホストアプリケーションにコピーします。Viewer.ReferenceScripts(...) の後にそのホストファイルを読み込んでください。フルデモ実装をコピーする際は、ヘルパーとその <nav id="toolbar"> マークアップを一緒に保管してください。
両方のリファレンスアプリケーションで使用されているパッケージ初期化順序を維持してください:
- Viewer、Search、Annotation のリソースを一緒に出力する。
- Viewer ツールバー、リボンマウント、Viewer マウントを一緒に描画する。
- まず
docViewerを初期化する。 - 各ライセンス済みリボンを作成し、同じ
objViewerに添付する。 - ドキュメントを開き、モジュールリクエスト用にトークンを保持する。
Doconut.TestApp.Distributed はこの正確な UI 構成と同じ Viewer ツールバーヘルパーを保持しています。追加の access リクエスト値と非同期レンダーリトライ設定は分散トランスポートに属し、Viewer、ツールバー、リボンの組み立て方法には影響しません。
サーバー側のガードは重要です。オプション機能が利用できない場合、そのスクリプトは出力されず、jQuery プラグイン関数も存在しません。
<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>埋め込みコンポーネントはそれぞれ独自のリボン DOM を生成します。Search には Find、Options、Results のグループがあり、Annotation には作成ツール、スタイルコントロール、保存アクション、オプションのエクスポート/画像アクションが含まれます。各バーは open()、close()、reset()、isOpen() を提供し、作成後は必ず一度だけ attach(objViewer) を呼び出してください。
上記の例では、起動を最小限に抑えるためにオプションのホストコールバックや Annotation のエクスポート/画像エンドポイントは省略しています。完全な機能別設定については 検索 と 注釈 を参照するか、ホスト所有の Viewer ツールバーをスタイル変更または置き換えるには カスタムテーマ をご覧ください。
ドキュメントを開く
サーバー側は 1 つのエンドポイントで、注入された Viewer サービスがドキュメントを開き、セッショントークンを返します。
app.MapPost("/api/open", async (Viewer viewer) =>
{
// The token is opaque — hand it to the widget, never log or persist it.
string token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
return Results.Ok(new { token });
});クライアントはそのトークンを取得し、objViewer.View(token) でウィジェットに渡します:
fetch('/api/open', { method: 'POST' })
.then(resp => resp.json())
.then(data => {
currentToken = data.token;
objViewer.View(currentToken);
});ドキュメントを閉じる
ユーザーがビューアを離れるか別のドキュメントを開く際は objViewer.Close() を呼び出してください。サーバー駆動のワークフローでは、viewer.CloseDocument(token) がキャッシュされたセッションを即座に削除し、レンダリングエンジンを破棄し、セキュリティマーカーを削除し、トークンを無効化します。スライディング有効期限でも最終的に同様のクリーンアップが行われますが、大きなドキュメントの場合は明示的なクローズが推奨されます。
完了したリクエストフローは次のとおりです:
AddDoconut + middleware
-> render CSS/scripts and mount div
-> initialize docViewer
-> OpenDocumentAsync
-> return opaque token
-> objViewer.View(token)
-> page/search/annotation requests
-> Close / CloseDocumentトークンはベアラークレデンシャルとして扱い、決してログに記録したり永続化したりせず、ウィジェットにのみ渡してください。サーバー上のライブドキュメントセッションを識別し、セッションが期限切れになると機能しなくなります — 新しいトークンを取得するにはドキュメントを再度開いてください。
実行方法
wwwroot/files/Sample.pdf に PDF を配置し、dotnet run を実行してウィジェットをホストするページを開きます。最初のページがビューアに表示され、左側にサムネイルパネルが表示されます。表示されない場合は、トラブルシューティング を参照してください。
ライセンスなしで得られるもの
ライセンスがない場合でも例外は発生しません。ビューアは通常通りレンダリングされますが、すべてのページに評価用の透かしが付加されます。Doconut がライセンスを取得する方法と取得後の変更点については、ライセンス設定 を参照してください。
このページは役に立ちましたか?