> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/get-started/libraries-and-frameworks/blazor.md).

# Build a Blazor PDF viewer with Apryse WebViewer SDK

Create a Blazor PDF viewer and editor with Apryse WebViewer. Learn how to integrate the SDK into your Blazor app and render PDFs in the viewer UI.

This guide shows how to build a Blazor PDF viewer using the Apryse [WebViewer SDK](/web/what-is-webviewer/overview.md). You'll learn how to integrate the SDK into a [Blazor](https://learn.microsoft.com/en-us/aspnet/core/blazor/?view=aspnetcore-10.0) application to render, view, and interact with PDF documents using the WebViewer UI.

You can also download ready-to-go GitHub samples for [Blazor server](https://github.com/ApryseSDK/webviewer-samples/tree/main/webviewer-blazor) and [Blazor wasm](https://github.com/ApryseSDK/webviewer-samples/tree/main/webviewer-blazor-wasm) to get started quickly. Additionally, explore the interactive [Showcase demo](https://showcase.apryse.com/) to see WebViewer's full capabilities in action.

## Prerequisites

This guide assumes basic familiarity with Blazor development. Before you start:

* Install [Node.js](https://nodejs.org/en/download) and npm. We recommend using the latest active LTS release.
* Install the [.NET 9+ SDK](https://dotnet.microsoft.com/en-us/download/dotnet/9.0) for your platform to build and run your application using C#.
* Install [Visual Studio Code](https://code.visualstudio.com/Download) or another code editor to develop and debug your code.
* Get your Apryse trial key.

{% @apryse-license-key/apryse-license-key platform="WEB\_VIEWER" variant="full" %}

## 1. Create a Blazor project

In this section, you’ll create a new Blazor application using the .NET CLI. This project provides the foundation for integrating Apryse WebViewer. If you already have a Blazor app, skip this and continue to [Install WebViewer](#id-2.-install-webviewer).

1. Before creating a project, open your terminal and confirm the .NET CLI is installed:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```shell
dotnet --version
```

{% endcode %}
{% endtab %}
{% endtabs %}

If this prints a version number, you're ready to proceed. If not, install the .NET SDK and rerun the command.

2. In your terminal, go to the directory where you want to create the project.
3. Create a new `webviewer-blazor` project:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```shell
dotnet new blazor -o webviewer-blazor
```

{% endcode %}
{% endtab %}
{% endtabs %}

4. Navigate to your new Blazor project directory, initialize your project, and generate a `package.json` file:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```shell
cd webviewer-blazor
npm init -y
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Info**

Flags are used to skip prompts during project configuration. The setup creates a `package.json` file with all default values. Select different options if preferred.
{% endhint %}

The final `package.json` should look like this:

{% tabs %}
{% tab title="JSON" %}
{% code lineNumbers="true" %}

```json
{
  "name": "webviewer-blazor",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## 2. Install WebViewer

Next, install the Apryse WebViewer SDK using npm. This command adds the [WebViewer package](https://www.npmjs.com/package/@pdftron/webviewer) to your project, allowing you to integrate the PDF viewer and editor into your Blazor application.

After navigating to your `webviewer-blazor` project directory, run the following command to install WebViewer:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```shell
npm i @pdftron/webviewer
```

{% endcode %}
{% endtab %}
{% endtabs %}

## 3. Copy WebViewer assets

WebViewer needs access to its static assets at runtime, including WebAssembly modules, HTML, and CSS files. In a Blazor project, you must copy these assets into the `public` directory so they can be served correctly. For more, see [Copying WebViewer static assets](/web/get-started/copy-assets.md).

1. From your project root, create the `wwwroot/lib/webviewer/public` directory if it doesn't already exist:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```shell
npx --yes shx mkdir -p wwwroot/lib/webviewer/public 
```

{% endcode %}
{% endtab %}
{% endtabs %}

2. Copy all WebViewer static assets from `node_modules/@pdftron/webviewer/public` into the new `wwwroot/lib/webviewer/public` directory:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```shell
npx --yes cpy-cli "node_modules/@pdftron/webviewer/public/**/*" wwwroot/lib/webviewer/public
```

{% endcode %}
{% endtab %}
{% endtabs %}

3. Copy the `webviewer.min.js` library file from `node_modules` to the `public` directory:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```shell
npx --yes cpy-cli node_modules/@pdftron/webviewer/webviewer.min.js wwwroot/lib/webviewer/public --flat 
```

{% endcode %}
{% endtab %}
{% endtabs %}

Your project should now include a similar structure:

{% code lineNumbers="true" %}

```
webviewer-blazor/
├── Components/
├── node_modules/
├── obj/
├── Properties/
└── wwwroot/
    ├── lib/
    │   ├── bootstrap/
    │   └── webviewer/
    │       └── public/
    │           ├── core/
    │           └── ui/
    │           └── webviewer.min.js
    ├── app.css
    └── favicon.png
└── ...
```

{% endcode %}

## 4. Create the PDF viewer

In this section, you’ll add WebViewer to your Blazor app by loading the WebViewer script and creating a Razor component that initializes the viewer and renders it in the UI, where it loads and displays a document.

1. In Visual Studio Code, replace the contents of the `Components/App.razor` file with the following and save:

{% tabs %}
{% tab title="Razor" %}
{% code title="Components/App.razor" lineNumbers="true" %}

```razor
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
    <link rel="stylesheet" href="@Assets["app.css"]" />
    <link rel="stylesheet" href="@Assets["webviewer-blazor.styles.css"]" />
    <ImportMap />
    <link rel="icon" type="image/png" href="favicon.png" />
    <HeadOutlet />
    <!-- Load the WebViewer library from the public assets folder --> 
    <script src="@Assets["lib/webviewer/public/webviewer.min.js"]"></script>
</head>

<body>
    <Routes />
    <script src="_framework/blazor.web.js"></script>
</body>

</html>
```

{% endcode %}
{% endtab %}
{% endtabs %}

2. Create a new `Components/WebViewer.razor` file, add the following code, and save:

<pre class="language-razor" data-line-numbers><code class="lang-razor">@* Container where the WebViewer UI is rendered *@
&#x3C;div id="viewer" style="width: 100%; height: 100vh; margin: 0 auto;">&#x3C;/div>

@* Initialize the Apryse WebViewer *@
&#x3C;script>
  window.WebViewer(
    {
      // Add location of WebViewer static files
      path: '/lib/webviewer/public',
      // Add PDF to load on startup
      initialDoc: 'https://apryse.s3.amazonaws.com/public/files/samples/WebviewerDemoDoc.pdf',
      // Replace with your Apryse license key
      licenseKey: '<code class="expression">visitor.claims.wvKey || "YOUR_LICENSE_KEY"</code>',
    },
    // Get element to mount the viewer into
    document.getElementById('viewer')
  ).then((instance) => {
    // Access the viewer API here if needed
  });
&#x3C;/script>
</code></pre>

{% hint style="info" %}
**Info**

If you're signed in with an Apryse account, your license key is automatically prepopulated in all code snippets.
{% endhint %}

3. Replace the `Components/Pages/Home.razor` file with the following and save:

{% tabs %}
{% tab title="Razor" %}
{% code title="Components/Pages/Home.razor" lineNumbers="true" %}

```razor
@page "/"

<WebViewer />
```

{% endcode %}
{% endtab %}
{% endtabs %}

## 5. Verify your output

You can now load and display a PDF document in the WebViewer UI. Run your Blazor application to launch WebViewer and see the PDF in your browser.

1. From your project directory, run the following command to start the application:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```shell
dotnet run
```

{% endcode %}
{% endtab %}
{% endtabs %}

A successful output looks similar to:

{% tabs %}
{% tab title="Shell" %}
{% code lineNumbers="true" %}

```shell
Building...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5067
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /path/to/your/project
```

{% endcode %}
{% endtab %}
{% endtabs %}

2. Open the localhost URL from your terminal to view the WebViewer UI and PDF document.

## Troubleshooting

**WebViewer fails to load due to MIME type issues**

If WebViewer doesn't load or you see a blank or partially rendered UI, the server may not be serving certain file types correctly. WebViewer includes files with `.wasm`, `.gz`, and `.br` extensions, which require proper MIME types that aren't always configured by default in Blazor.

To fix this, configure the application to serve these file types by updating `Program.cs`:

{% tabs %}
{% tab title="C#" %}
{% code title="Program.cs" lineNumbers="true" %}

```csharp
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".res"] = "application/octet-stream";
provider.Mappings[".pexe"] = "application/x-pnacl";
provider.Mappings[".nmf"] = "application/octet-stream";
provider.Mappings[".mem"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";
provider.Mappings[".gz"] = "application/gzip";
provider.Mappings[".br"] = "application/brotli";

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(Directory.GetCurrentDirectory(), "wwwroot")),
        ContentTypeProvider = provider
});

```

{% endcode %}
{% endtab %}
{% endtabs %}

Restart the application after making these changes.

## Get started video

In this 5-minute video, learn how to install and integrate the Apryse WebViewer SDK into a Blazor project.

{% embed url="<https://www.youtube.com/embed/6NLEkjs4ybI?si=O3h_xoxPYoP0xqQJ>" %}
Integrate the WebViewer SDK into an ASP.NET Core–hosted Blazor project.
{% endembed %}

## Next steps

<a href="/web/what-is-webviewer/usage.md" class="button primary">Usage</a><a href="/web/get-started/guides.md" class="button primary">Guides</a><a href="/web/get-started/samples.md" class="button primary">Samples</a><a href="https://sdk.apryse.com/api/web/index.html" class="button primary">API docs</a>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/get-started/libraries-and-frameworks/blazor.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
