# Blazor

> Use the Blazor DocumentEditor and DocumentViewer components: packages, render mode, Program.cs for both, the viewer setup, C# methods, merging and JS interop.

- **Product:** TX Text Control .NET Server
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET Server > Integration Guide > Blazor
- **4995 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/integration/blazor/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/integration/blazor/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/integration/blazor/llms-full.txt

---

Blazor applications program TX Text Control in C#. The `DocumentEditor` and `DocumentViewer` components run with interactive server rendering, so the code of a page works with their documents directly on the server: it loads files into them, saves their content and merges templates with `ServerTextControl`, while the JavaScript API remains available for tasks in the browser.

[Document Editor: Blazor](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-editor/blazor/llms-full.txt) adds a first editor to a new Blazor Web App. Larger Blazor applications often go further, with both components in one application, the Document Viewer, the C# members of the editor, a merge preview and calls of the JavaScript API.

### Packages and Render Mode

| Package | Source | Purpose |
|---|---|---|
| `TXTextControl.Web.Blazor.DocumentEditor` | nuget.org | The `DocumentEditor` component |
| `TXTextControl.Web.Blazor.DocumentViewer` | nuget.org | The `DocumentViewer` component |
| `TXTextControl.Web` | Text Control Private NuGet Feed | The WebSocket middleware of the editor |
| `TXTextControl.Web.DocumentEditor.Backend` | Text Control Private NuGet Feed | The backend process of the editor and the hosted service that starts it |
| `TXTextControl.Web.DocumentViewer` | Text Control Private NuGet Feed | The backend of the viewer |
| `TXTextControl.TextControl.Core.SDK` | Text Control Private NuGet Feed | The document engine |

Both Blazor packages target .NET 8 and work in a Blazor Web App. A page that contains one of the components uses interactive server rendering:

```razor
@rendermode InteractiveServer
```

Blazor sets the render mode per page or component, so other parts of the application can use other render modes. The TX Text Control components behave differently in them:

| Component | Interactive server rendering | Interactive WebAssembly and Auto rendering |
|---|---|---|
| `DocumentEditor` | Supported | Not possible. Components with these render modes belong in the *.Client* project, and adding the editor package there fails the build with error NETSDK1082: "There was no runtime pack for Microsoft.AspNetCore.App available for the specified RuntimeIdentifier 'browser-wasm'." |
| `DocumentViewer` | Supported | The component works in the *.Client* project with its backend in the server project. `LoadDocument` completes only after the viewer is ready; called in `OnLoad`, it doesn't return. Load documents later, for example from a user action. |

### Configure Program.cs for Both Components

The Blazor application hosts the backends of both components. Start with the *Program.cs* of [Configure Program.cs](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-editor/blazor/#configure-program-cs) in the Blazor tutorial, which starts the editor backend and adds the WebSocket middleware, and add the backend of the viewer:

1. At the top of the file, add the namespace of the viewer:

```csharp
using TXTextControl.Web.MVC.DocumentViewer;
```

1. Before `var app = builder.Build();`, register the controllers, which include the controller of the viewer:

```csharp
builder.Services.AddControllers();
```

1. Add `app.UseRouting();` and `app.UseTXDocumentViewer();` before the Razor components are mapped. The README of the viewer package places them around `app.UseAntiforgery();`:

```csharp
app.UseRouting();
app.UseAntiforgery();
app.UseTXDocumentViewer();
```

### Add the Document Viewer

The `DocumentViewer` component displays documents, form fields and signature fields. It has no size parameters, so place it in a container with a size. The following page loads *Documents/template.docx* into the viewer:

```razor
@page "/viewer"
@rendermode InteractiveServer
@using TXTextControl.Web.Blazor.DocumentViewer

<div style="width: 1000px; height: 600px;">
    <DocumentViewer @ref="_documentViewer" />
</div>

<button class="btn btn-primary mt-3" @onclick="ButtonLoad">Load Document</button>

@code {
    private DocumentViewer? _documentViewer;

    private async Task ButtonLoad()
    {
        byte[] document = await File.ReadAllBytesAsync("Documents/template.docx");
        await _documentViewer!.LoadDocument(document);
    }
}
```

The code works as follows:

- `@ref` stores a reference to the component, so the C# code can call its methods.
- `LoadDocument` takes the document as a byte array and sends it to the viewer. The method has no parameter for a document name.

The component has these parameters:

| Parameter | Description |
|---|---|
| `BasePath` | The URL of the viewer backend. By default, the viewer uses the Blazor application itself. |
| `SignatureSettings` | The signature settings for collecting signatures, with the signer, the signature boxes and the URL that receives the signed document. Define them when the viewer is initialized. |
| `UserNames` | An array of user names. |
| `OnLoad` | An event that the component raises when it has loaded its script. With interactive server rendering, `LoadDocument` can be called in its handler. |

The blog article [E-Sign Comes to Blazor: Document Viewer 33.0.1 Released](https://www.textcontrol.com/blog/2025/04/24/e-sign-comes-to-blazor-document-viewer-33-0-1-released/) collects signatures with `SignatureSettings`, and [Digital Signatures](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/digital-signatures/llms-full.txt) in the Document Viewer section explains the signing process.

### Program the Editor in C#

The `DocumentEditor` component has these parameters:

| Parameter | Default | Description |
|---|---|---|
| `Width` and `Height` | `800px` and `600px` | The size of the editor |
| `WebSocketURL` | The address of the Blazor application with `api/TXWebSocket` | The WebSocket URL of the backend. A value must start with `wss://` or `ws://`. |
| `ContainerID` | A generated ID | The ID of the container element |
| `OnLoad` |  | An event raised when the editor is ready and connected |

Its methods work on the document of the connected editor on the server:

| Methods | Purpose |
|---|---|
| `LoadDocumentAsync` | Load a document from a file path, a `FileStream`, a byte array or a string. The format is a [StreamType](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-web/streamtype/enumeration/llms-full.txt), [BinaryStreamType](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-web/binarystreamtype/enumeration/llms-full.txt) or [StringStreamType](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-web/stringstreamtype/enumeration/llms-full.txt) value of `TXTextControl.Web`. |
| `SaveDocumentAsync` | Save the document to a file path or a `FileStream`, or return it as a byte array or a string |
| `SetEditModeAsync`, `GetEditModeAsync` | Set or get the [EditMode](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-web/editmode/enumeration/llms-full.txt), for example to show a document read-only |
| `SetUserNamesAsync`, `GetUserNamesAsync` | Set or get the users who have access to editable regions |
| `GetSelectionAsync`, `SetSelectionAsync` | Get or set the [Selection](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-web/selection/llms-full.txt) |
| `GetTextPartsAsync` | Get the [TextPartCollection](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-web/textpartcollection/llms-full.txt) of the document |

Further methods show or hide control characters, table grid lines, text frame marker lines and document target markers, enable or disable context menus and set the background and status bar colors. The component package includes no reference documentation; the names above are those of the package's public API.

The methods find the session of the editor through the WebSocket middleware in the process of the Blazor application. They work only when the application itself hosts the middleware and the backend, as configured above. When `WebSocketURL` points to another application, the editor connects and raises `OnLoad`, but `LoadDocumentAsync` throws a `NullReferenceException`; in that setup, only the JavaScript API reaches the document.

### Preview a Merged Template

The following page combines both components: the user edits a template in the editor, and a button merges it with *Documents/data.json* on the server and shows the result in the viewer.

```razor
@page "/"
@rendermode InteractiveServer
@using TXTextControl.Web.Blazor.DocumentViewer

<TXTextControl.Web.Blazor.DocumentEditor.DocumentEditor
    @ref="_documentEditor" OnLoad="DocumentEditorLoaded" Width="800px" Height="500px" />

<button class="btn btn-primary mt-3" @onclick="ButtonPreview">Preview</button>

<div style="width: 800px; height: 500px;">
    <DocumentViewer @ref="_documentViewer" />
</div>

@code {
    private TXTextControl.Web.Blazor.DocumentEditor.DocumentEditor _documentEditor = default!;
    private DocumentViewer? _documentViewer;

    private async Task DocumentEditorLoaded()
    {
        await _documentEditor.LoadDocumentAsync("Documents/template.docx",
            TXTextControl.Web.StreamType.WordprocessingML);
    }

    private async Task ButtonPreview()
    {
        // Get the edited template from the editor
        byte[] template = await _documentEditor.SaveDocumentAsync(
            TXTextControl.Web.BinaryStreamType.InternalUnicodeFormat);
        byte[] result;

        using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
        {
            tx.Create();
            tx.Load(template, TXTextControl.BinaryStreamType.InternalUnicodeFormat);

            using (TXTextControl.DocumentServer.MailMerge mailMerge =
                new TXTextControl.DocumentServer.MailMerge { TextComponent = tx })
            {
                mailMerge.MergeJsonData(File.ReadAllText("Documents/data.json"));
            }

            tx.Save(out result, TXTextControl.BinaryStreamType.InternalUnicodeFormat);
        }

        await _documentViewer!.LoadDocument(result);
    }
}
```

The code works as follows:

- `OnLoad` loads the template as soon as the editor is ready.
- `SaveDocumentAsync` returns the content of the editor as a byte array in the internal format of TX Text Control. Await the method instead of reading its `Result`, which blocks the thread.
- [ServerTextControl](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/llms-full.txt) loads the template, and [MailMerge.MergeJsonData](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-documentserver/mailmerge/mergejsondata-method/llms-full.txt) merges it with the JSON data. The document engine classes use `TXTextControl.BinaryStreamType`, while the editor methods use `TXTextControl.Web.BinaryStreamType`.
- `LoadDocument` shows the merged document in the viewer. The template in the editor stays unchanged.

The blog article [TX Text Control for Blazor: Mail Merge Integration Tutorial](https://www.textcontrol.com/blog/2025/03/25/tx-text-control-for-blazor-mail-merge-integration-tutorial/) loads the merge result back into the editor and exports it as PDF.

### Call the JavaScript API

Some tasks run in the browser, such as reacting to user interactions or switching on track changes. The global `TXTextControl` object is available in the page, and the C# code calls JavaScript functions with `IJSRuntime`. Microsoft recommends placing JavaScript for components with an interactive render mode in files rather than in `script` tags of *.razor* files. Create *wwwroot/js/editor.js*:

```javascript
function enableTrackChanges() {
    TXTextControl.setIsTrackChangesEnabled(true);
}
```

Reference the file in *Components/App.razor* after the Blazor script:

```razor
<script src="@Assets["_framework/blazor.web.js"]"></script>
<script src="js/editor.js"></script>
```

The page calls the function:

```razor
@page "/review"
@rendermode InteractiveServer
@inject IJSRuntime JS

<TXTextControl.Web.Blazor.DocumentEditor.DocumentEditor Width="800px" Height="500px" />

<button class="btn btn-primary mt-3" @onclick="ButtonTrackChanges">Track Changes</button>

@code {
    private async Task ButtonTrackChanges()
    {
        await JS.InvokeVoidAsync("enableTrackChanges");
    }
}
```

The code works as follows:

- *App.razor* loads the script once for the whole application, so the function is available on every page, also after Blazor's enhanced navigation between pages.
- `@inject IJSRuntime JS` provides the JavaScript runtime of the page, and `InvokeVoidAsync` calls the function `enableTrackChanges` in the browser.
- [TXTextControl.setIsTrackChangesEnabled](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript/txtextcontrol/setistrackchangesenabled-method/llms-full.txt) switches on track changes in the editor. The property `isTrackChangesEnabled` does the same, but it's obsolete.
- Call such functions after the editor is ready, for example from a button or from the `OnLoad` event of the component.

For calls in the other direction, from JavaScript to C#, pass a `DotNetObjectReference` to a JavaScript function, which then calls a method marked with `[JSInvokable]`. Dispose the reference when the component is disposed, so that it doesn't leak memory. The blog article [Using TX Text Control in a Blazor Server App with .NET 8](https://www.textcontrol.com/blog/2024/01/25/using-tx-text-control-in-an-blazor-server-app-with-net-8/) shows the pattern from before the components were released, and [Call .NET methods from JavaScript functions in ASP.NET Core Blazor](https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-dotnet-from-javascript) describes it in detail. [JavaScript API](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/javascript-api/llms-full.txt) and [Events](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/events/llms-full.txt) describe the objects and events of the editor.

### Use Another Backend for the Viewer

The viewer backend doesn't have to run in the Blazor application. Set `BasePath` to the URL of another ASP.NET Core application that hosts the viewer:

```razor
<DocumentViewer @ref="_documentViewer" BasePath="https://localhost:7118" />
```

That application runs `UseTXDocumentViewer` and needs a CORS policy that allows the origin of the Blazor application, as [Configure Program.cs for Separate Frontends](https://docs.textcontrol.com/tx-text-control-dotnet-server/integration/aspnet-core/#configure-program-cs-for-separate-frontends) shows. Omit the trailing slash, because the component appends the paths of its scripts to the URL.

### Recognize Older Blazor Articles

Articles written before the components were released in version 33.0 use the **Blazor Server App** template and connect the JavaScript API of the editor or viewer to C# with their own interop code. The components replace this code. The getting started articles about the components from 2025 install the Blazor package from nuget.org and the engine and viewer packages from the offline package source of an installed trial version; with the private NuGet feed, install those packages as described above.

### Next Steps

- [Document Editor: Blazor](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-editor/blazor/llms-full.txt): the first editor in a new Blazor Web App.
- [ASP.NET Core](https://docs.textcontrol.com/tx-text-control-dotnet-server/integration/aspnet-core/llms-full.txt): services and dependency injection for `ServerTextControl`.
- [Mail Merge and Reporting](https://docs.textcontrol.com/tx-text-control-dotnet-server/mail-merge/llms-full.txt): templates, merge fields and data sources for the merge preview.
- [WebSocket Architecture](https://docs.textcontrol.com/tx-text-control-dotnet-server/integration/websockets/llms-full.txt): the connection between the editor and the backend in detail.

---

## Nearby

- **Previous:** [JavaScript](https://docs.textcontrol.com/tx-text-control-dotnet-server/integration/javascript/llms-full.txt)
- **Next:** [REST Services](https://docs.textcontrol.com/tx-text-control-dotnet-server/integration/rest-services/llms-full.txt)
