クイックスタート

数分で最初のドキュメントをレンダリング

このハンドブックは、空の Program.cs からブラウザでドキュメントがレンダリングされるまでの ASP.NET Core アプリを案内します:サーバー登録、完全な Viewer パッケージ(Viewer ツールバー、Viewer マウント、オプションの検索/注釈リボン)、アセット参照、クライアント初期化、ドキュメントのオープン、そして実行。

サーバー設定

AddDoconut() はサービスを登録します; UseDoconutResources()UseDoconut() はミドルウェアを接続します。リソース呼び出しは最初に行う必要があります。セッション呼び出しも必要です — Doconut のデフォルトドキュメントセキュリティは、すべてのページリクエストを ASP.NET セッション状態と照合して検証します。すでに インストール 時に Doconut を登録しましたか?次のセクションへ進んでください。

csharp
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 つのパス設定を揃えておきます:

csharp
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 を使用します:

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

ツールバー、モジュールマウント、Viewer サーフェスを 1 つのページ構成として扱います。Search と Annotation は埋め込みリボンをオプションのマウントに注入しますが、これらのモジュールは単独では使用されません:常に同じページの Viewer にアタッチされます。Doconut.TestAppDoconut.TestApp.Distributed と同じ順序を使用してください:

html
<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 プラグインなので、jQuery はビューアスクリプトより先にロードする必要があります:

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

完全な Viewer パッケージを取得するには、Viewer とモジュールのリソースを一緒に要求します:

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

IncludeViewerCssIncludeViewerScripts は必須のコアフラグです。これら、Viewer マウント、そして docViewer インスタンスなしで Search や Annotation リボンの例を公開しないでください。ReferenceCssReferenceScripts は、現在のライセンスがその機能を許可していない場合、オプションモジュールのリソースを省略しますが、コア Viewer は起動します。

ビューアの初期化

クライアント側ウィジェットは jQuery プラグインです。以下は実際の初期化オプションの最小セットです(疑似コードではありません):

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

オプションのケースは実際に混在しています — showThumbsautoLoadpageZoom は camelCase ですが、FitTypeBasePathResPath は PascalCase です。一貫した規則はなく、ケースが間違っているとオプションは黙って無視されます(ウィジェットは例外を投げずにデフォルトにフォールバックします)。

完全な Viewer パッケージの組み立て

.NET 6 のリファレンスアプリケーションは、以下のパーツを 1 ページにまとめてインストールします:

パッケージの部品要件接続方法
Viewer リソース、マウント、そして objViewer必須コアドキュメントレンダラ
Viewer ツールバーリファレンス構成で必須ホストマークアップ;ボタンは同じ objViewer を呼び出す
Search リボンオプション、ライセンスモジュールdoconutSearchBar(...).attach(objViewer)
Annotation リボンオプション、ライセンスモジュールdoconutAnnotationBar(...).attach(objViewer)

メインの Viewer ツールバーはホストマークアップですが、Viewer と一緒にインストールされ、単独のコントロールとして文書化してはいけません。これにより、レイアウト、ラベル、アイコン、認可ルールはアプリケーション側で管理され、すべてのボタンが同じ Viewer インスタンスを操作します:

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>

完全なリファレンスツールバーは、回転、サムネイル、印刷、全画面、レイアウト、ボタン状態ヘルパー用に wwwroot/js/viewerToolbar.js をホストアプリケーションにコピーします。Viewer.ReferenceScripts(...) の後にそのホストファイルをロードしてください。フルデモ実装をコピーする際は、ヘルパーとその <nav id="toolbar"> マークアップを一緒に保ってください。

両方のリファレンスアプリケーションで使用されるパッケージ初期化順序を保持してください:

  1. Viewer とライセンスモジュールの CSS を出力する。
  2. Viewer ツールバー、Search/Annotation のマウント、そして Viewer マウントを一緒にレンダリングする。
  3. Viewer とライセンスモジュールのスクリプトを出力する。
  4. ホストアプリケーションの viewerToolbar.js をロードする。
  5. docViewer を初期化し、生成された objViewer を保持する。
  6. 各ライセンス対象の Search または Annotation リボンを初期化する。
  7. すべてのリボンで attach(objViewer) を呼び出す。
  8. ドキュメントを開き、Viewer とモジュールのリクエスト用にトークンを保持する。

Doconut.TestApp.Distributed はこの正確な UI 構成と同じ Viewer ツールバー ヘルパーを保持しています。追加の access リクエスト値と非同期レンダーリトライ設定は分散トランスポートに属し、Viewer、ツールバー、またはリボンの組み立て方法は変わりません。

サーバー側のガードは重要です:オプション機能が利用できない場合、そのスクリプトは出力されず、jQuery プラグイン関数も存在しません。

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>

埋め込みコンポーネントはそれぞれ独自のリボン DOM を生成します。Search には Find、Options、Results のグループが含まれ、Annotation には作成ツール、スタイルコントロール、保存アクション、オプションのエクスポート/画像アクションがあります。各バーは open(), close(), reset(), isOpen() を提供し、作成後は必ず一度だけ attach(objViewer) を呼び出してください。

上記の例は、起動を最小限に抑えるためにオプションのホストコールバックと Annotation のエクスポート/画像エンドポイントを省略しています。完全な機能別設定については SearchAnnotations を参照し、ホスト所有の Viewer ツールバーをスタイル変更または置き換えるには Custom Themes をご覧ください。

ドキュメントを開く

サーバー側は 1 つのエンドポイントで、注入された Viewer サービスがドキュメントを開き、セッショントークンを返します。

csharp
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) でウィジェットに渡します:

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

ドキュメントを閉じる

ユーザーがビューアを離れるか代替ドキュメントを開くときは objViewer.Close() を呼び出してください。サーバー駆動のワークフローでは、viewer.CloseDocument(token) がキャッシュされたセッションを即座に削除し、レンダリングエンジンを破棄し、セキュリティマーカーを削除し、トークンを無効化します。スライディング有効期限でも最終的に同様のクリーンアップが行われますが、大きなドキュメントの場合は明示的に閉じることが推奨されます。

完了したリクエストフローは次のとおりです:

text
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 がライセンスを取得する方法と取得後の変更点については License Setup を参照してください。

このページは役に立ちましたか?