# Import and Export

> Export and import Document Viewer annotations: the JSON format, storing annotations per document through a controller, loading them again and sharing them live.

- **Product:** TX Text Control .NET Server
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET Server > Document Viewer > Annotations > Import and Export
- **2700 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/annotations/import-export/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/annotations/import-export/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/annotations/import-export/llms-full.txt

---

Keeping review results in your database or sharing annotations between users means storing the annotations of the Document Viewer and restoring them. The building blocks are the JSON format, exporting and loading annotations, storing them for each document on your server and processing them on the server.

The examples extend the application of the [ASP.NET Core](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-viewer/aspnet-core/llms-full.txt) tutorial and use the file *App\_Data/template.docx*.

### How Annotations Are Stored

The viewer keeps annotations separately from the document. [export](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript-document-viewer/annotations/export-method/llms-full.txt) returns all annotations as a JSON string, and [load](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript-document-viewer/annotations/load-method/llms-full.txt) loads annotations from such a string. The document stays unchanged, and your application decides where the annotations are stored, who may see them and how long they are kept. A common design stores the original document once and the annotations in a table of their own, with the ID of the document, the user and the time of the last change.

The format is the same for all document types, so the same review process works for DOCX, PDF and the other formats. Store annotations with the document they belong to: the positions in the JSON refer to the pages and text of that document.

### The JSON Format

The JSON is an array with an inner array for each page of the document, in the order of the pages. Pages without annotations have an empty array. Every annotation is an object with these properties:

| Property | Contains |
|---|---|
| `pen` | The type of the annotation and its attributes, such as the color |
| `user` | The user who created the annotation |
| `time` | The time of creation in milliseconds since January 1, 1970 |
| `comments` | An array of comments; see [Comments](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/annotations/comments/#the-structure-of-a-comment) |
| `id` | A unique identifier |
| `status` | A status such as `accepted`, when one is set |

The pen and the other properties depend on the type:

| Annotation | `pen.type` | Further properties |
|---|---|---|
| Note | `comment` | `location` with `x` and `y`; the pen has `objectWidth` and `objectHeight` |
| Text highlight | `highlight` | The pen has `color`, `start`, `end` and the highlighted `text`; no `location` |
| Text | `text` | `text` and `location`; the pen has the color and the font attributes |
| Signature | `signature` | `location` and `image`, the signature as a data URL |
| Drawing | none | `lines`, an array of points; the pen has `width`, `color` and other line attributes |

Some properties have changed between versions of the viewer, so read only the properties your application needs and check that they exist.

### Store and Load Annotations for a Document

The following example stores the annotations of *template.docx* in a JSON file on the server and loads them again when the page opens. Create *Controllers/AnnotationsController.cs*:

```csharp
using Microsoft.AspNetCore.Mvc;

public class AnnotationsController : Controller
{
    private static readonly string StorageFolder = Path.Combine("App_Data", "Annotations");

    // Return the stored annotations of a document, or an empty array
    [HttpGet]
    public IActionResult Load(string documentId)
    {
        string path = GetPath(documentId);

        if (!System.IO.File.Exists(path))
        {
            return Content("[]", "application/json");
        }

        return Content(System.IO.File.ReadAllText(path), "application/json");
    }

    // Store the annotations that the viewer exported
    [HttpPost]
    public async Task<IActionResult> Save(string documentId)
    {
        using var reader = new StreamReader(Request.Body);
        string json = await reader.ReadToEndAsync();

        Directory.CreateDirectory(StorageFolder);
        await System.IO.File.WriteAllTextAsync(GetPath(documentId), json);

        return Ok();
    }

    private static string GetPath(string documentId) =>
        Path.Combine(StorageFolder, Path.GetFileName(documentId) + ".json");
}
```

Replace the content of *Views/Home/Index.cshtml*:

```cshtml
@using TXTextControl.Web.MVC.DocumentViewer

<div style="width: 800px; height: 600px;">

@Html.TXTextControl().DocumentViewer(settings => {
    settings.DocumentPath = "App_Data/template.docx";
    settings.Dock = DocumentViewerSettings.DockStyle.Fill;
}).Render()

</div>

<input type="button" id="saveAnnotations" value="Save Annotations" />

<script>
    var documentId = "template";

    window.addEventListener("documentViewerLoaded", async function () {
        TXDocumentViewer.annotations.showToolbar(true);

        var response = await fetch("/Annotations/Load?documentId=" + encodeURIComponent(documentId));
        TXDocumentViewer.annotations.load(await response.text());
    });

    document.getElementById("saveAnnotations").addEventListener("click", async function () {
        await fetch("/Annotations/Save?documentId=" + encodeURIComponent(documentId), {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: TXDocumentViewer.annotations.export()
        });
    });
</script>
```

The code works as follows:

- The `Load` action returns the stored JSON of a document, or `[]` if nothing has been stored yet. The `Save` action writes the posted JSON into a file for each document. In your application, replace the files with a table of your database.
- When the viewer is loaded, the script requests the annotations of the document and passes them to `load`.
- **Save Annotations** posts the result of `export` to the `Save` action.

Run the application, add a note and click **Save Annotations**. Reload the page: the note appears again.

To save automatically, post the annotations in a handler of the `annotationsChanged` event instead of a button, as the [ASP.NET Core](https://docs.textcontrol.com/tx-text-control-dotnet-server/getting-started/document-viewer/aspnet-core/#use-the-javascript-api) tutorial shows with the console.

### Store the Annotations in the Document

Instead of storing annotations separately, your code can save the document with them: [saveDocument](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript-document-viewer/documentviewercontroller/savedocument-method/llms-full.txt) with [embedAnnotations](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/javascript-document-viewer/documentsavesettings/embedannotations-property/llms-full.txt) set to `true` stores the annotations in the saved document. [Saving Documents](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/saving/llms-full.txt) shows how the saved document is sent to your server.

When users place signatures as annotations, your server can also merge them into the document as images with `ServerTextControl`. The blog article [Merging Signature Annotations into Documents](https://www.textcontrol.com/blog/2022/10/19/merging-signature-annotations-into-documents/) reads the `signature` annotations from the JSON and inserts their images at their positions.

### Share Annotations Live

Because the JSON is small, it can be sent to other users while they view the same document. In a handler of `annotationsChanged`, the viewer of one user exports the annotations and sends them, for example over SignalR, and the viewers of the other users load them. The blog article [DocumentViewer Collaboration: Live Share Document Annotations](https://www.textcontrol.com/blog/2021/06/08/documentviewer-collaboration-live-share-document-annotations/) builds this with a sample on GitHub.

### Next Steps

- [Comments](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/annotations/comments/llms-full.txt): read the comments of the exported annotations.
- [Saving Documents](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/saving/llms-full.txt): save the document with its annotations and form values.
- [Events](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/events/llms-full.txt): react when annotations change.

---

## Nearby

- **Previous:** [Highlights](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/annotations/highlights/llms-full.txt)
- **Next:** [Tracked Changes](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-viewer/tracked-changes/llms-full.txt)
