ReportingCloud

ASP.NET Core

Topic

A .NET developer reaches ReportingCloud with the TXTextControl.ReportingCloud NuGet package, the .NET SDK that wraps the Web API in C# classes. What follows builds an ASP.NET Core MVC application on .NET 10 that merges a template of the Sample Template Gallery with data from C# objects and shows the PDF in the browser. You add the template to your storage, create the project, install the package and write a model and one controller action; the merging itself happens at ReportingCloud.

Prerequisites

  • A ReportingCloud account and an API key. A trial account is enough. Creating an Account shows how to sign up, and API Keys how to create a key in the ReportingCloud portal.
  • The .NET 10 SDK. The steps were written with Visual Studio 2026 and .NET 10 (Long Term Support). You can use the .NET CLI with any editor instead of Visual Studio.

Add the Template to Your Storage

The application merges gallery_using-prefixes.tx, a template of the Sample Template Gallery in the portal. A template is merged by its name, so it has to be in your template storage first:

  1. Log in to the portal and open the gallery page of the template, https://portal.reporting.cloud/Gallery/Details/?template=gallery_using-prefixes.tx.
  2. Click Add to My Templates.

The template now appears on the My Templates page of the portal. Template Storage describes the gallery and its other templates.

Create the Project

Use either Visual Studio or the .NET CLI.

Visual Studio

  1. In Visual Studio 2026, create a new project by choosing Create a new project.
  2. Select ASP.NET Core Web App (Model-View-Controller) as the project template and confirm with Next.
  3. Enter MyReportingApp as the project name, choose a location and confirm with Next.
  4. Choose .NET 10.0 (Long Term Support) as the Framework and confirm with Create.

.NET CLI

  1. Open a terminal and create a new MVC application:

    dotnet new mvc -n MyReportingApp
    
  2. Change to the project directory:

    cd MyReportingApp
    

Install the NuGet Package

TXTextControl.ReportingCloud is published on nuget.org by Text Control GmbH. Its current version, 1.205.500, contains builds for .NET Framework 4.5, .NET Core 1.1 and .NET Standard 1.3; a .NET 10 project uses the .NET Core 1.1 build. The package brings Newtonsoft.Json 10.0.3 along, which it uses to send and read JSON.

Visual Studio

  1. In Solution Explorer, select your project and choose Manage NuGet Packages... from the Project main menu.
  2. Select nuget.org as the Package source.
  3. Browse for TXTextControl.ReportingCloud and install it.

.NET CLI

Add the package to the project:

dotnet add package TXTextControl.ReportingCloud

NuGet warns that some of the package's dependencies have known vulnerabilities. The project builds and runs nevertheless; Troubleshooting explains the warnings.

Set the API Key

The application reads the API key from the environment variable REPORTINGCLOUD_API_KEY, which keeps it out of your source code.

  • With the .NET CLI, set the variable in the terminal before you start the application, in bash with export REPORTINGCLOUD_API_KEY="<API key>" or in PowerShell with $env:REPORTINGCLOUD_API_KEY = "<API key>".

  • In Visual Studio, add it to the environmentVariables of the launch profile that you start, such as https, in Properties/launchSettings.json:

    "environmentVariables": {
      "ASPNETCORE_ENVIRONMENT": "Development",
      "REPORTINGCLOUD_API_KEY": "<API key>"
    }
    

    The file is part of the project. Don't commit it with the key to source control.

Replace <API key> with a key from the Manage Account page of the portal.

Create the Data Model

The data that the template receives is a C# object. In the Models folder, add a class file Report.cs with the following code:

namespace MyReportingApp.Models;

public class Report
{
    public Customer customer { get; set; } = new();
}

public class Customer
{
    public string name { get; set; } = "";
    public string street { get; set; } = "";
    public string zipcode { get; set; } = "";
    public string city { get; set; } = "";
    public string country { get; set; } = "";
    public List<Contact> contacts { get; set; } = new();
}

public class Contact
{
    public string firstname { get; set; } = "";
    public string name { get; set; } = "";
}

The property names are the names that the template uses: the values fill its merge fields, placeholders named after the properties, and the list contacts fills a merge block, a part of the template that is repeated for each element. They are written in lowercase like the field names, against the usual C# style; the Web API matches merge field and merge block names regardless of case, so a property FirstName would fill the field firstname as well. Merge Data explains how nested objects such as customer and lists map to the template.

Write the Controller

In the Controllers folder, add a class ReportController.cs with the following code:

using Microsoft.AspNetCore.Mvc;
using MyReportingApp.Models;
using TXTextControl.ReportingCloud;

namespace MyReportingApp.Controllers;

public class ReportController : Controller
{
    public IActionResult Pdf()
    {
        // Read the API key from the environment, never from source code
        string apiKey = Environment.GetEnvironmentVariable("REPORTINGCLOUD_API_KEY")
            ?? throw new InvalidOperationException("Set the environment variable REPORTINGCLOUD_API_KEY.");

        // Every request of this instance authenticates with the API key
        ReportingCloud reportingCloud = new ReportingCloud(apiKey);

        // The data whose property names match the merge fields of the template
        Report report = new Report
        {
            customer = new Customer
            {
                name = "Text Control, LLC",
                street = "2778 Shannon Willow Rd.",
                zipcode = "28226",
                city = "Charlotte",
                country = "United States",
                contacts = new List<Contact>
                {
                    new Contact { firstname = "Peter", name = "Bishop" }
                }
            }
        };

        MergeBody mergeBody = new MergeBody { MergeData = report };

        // Merge the template from the template storage into a PDF
        List<byte[]> documents = reportingCloud.MergeDocument(
            mergeBody, "gallery_using-prefixes.tx", ReturnFormat.PDF);

        // Without a file name, the browser displays the PDF
        return File(documents[0], "application/pdf");
    }
}

What the Code Does

  • ReportingCloud, in the namespace TXTextControl.ReportingCloud, is the class with a method for each endpoint of the Web API; those of the two tracked-changes endpoints are in its property Processing.Review. The constructor with one string takes an API key and sends it with every request as Authorization: ReportingCloud-APIKey <key>. Other constructors take a user name and password instead, and a Uri for a base address other than https://api.reporting.cloud.
  • MergeBody is the body of the merge request. MergeData takes the data as any object, which the SDK sends as JSON; the optional properties Template and MergeSettings carry a template that is not stored and the settings of the merge.
  • MergeDocument sends the request POST /v1/document/merge with the template name and the return format and waits for the answer. It returns a List<byte[]> with one element per created document, already decoded from Base64. Its optional parameters append and test default to true and false, and the SDK sends both with every request, here as append=True&test=False.
  • ReturnFormat.PDF selects the format. The merge endpoint also returns PDFA, RTF, DOC, DOCX, HTML, TX and TXT; a trial account creates no PDF/A.
  • File returns the PDF with the content type application/pdf and without a file name, so the browser displays it. Pass a file name as the third argument, such as File(documents[0], "application/pdf", "report.pdf"), to have the browser download it instead.

The SDK lowercases the capital letters at the start of every property name when it serializes the data: a property ZipCode would be sent as zipCode and ID as id. Properties that already have the names of the template's fields, as in Report, are sent unchanged. Merge Data describes how the SDK serializes objects.

Run the Application

  1. Start the application: in Visual Studio, press F5; with the .NET CLI, run dotnet run in the project directory, in the terminal where you set the API key. The console shows the address the application listens on, such as http://localhost:5082.
  2. Open /Report/Pdf below that address in the browser, for example http://localhost:5082/Report/Pdf.

The browser shows the merged PDF: the heading of the gallery template and the address of Text Control, LLC with the contact Peter Bishop below the company name. A trial account adds the ReportingCloud logo to every document.

Browser showing the PDF merged from the gallery template with the company name, the contact Peter Bishop and the address

Each call of the action is a merge request and counts 1 against the monthly document quota of your plan.

Troubleshooting

MergeDocument and the other methods of the SDK throw an ArgumentException when the Web API answers with an error. Its message is the response body of the Web API; the status code is not part of it. In the Development environment, the browser shows the exception on the error page of ASP.NET Core.

  • The API key is not set. The action throws its own exception:

    System.InvalidOperationException: Set the environment variable REPORTINGCLOUD_API_KEY.
    

    The application didn't receive the variable. Set it in the terminal that runs dotnet run, or in the launch profile that Visual Studio starts, and start the application again.

  • The template is not found. The Web API answers with status code 400 when the template is not in your template storage. Add gallery_using-prefixes.tx from the gallery as Add the Template to Your Storage shows, and check that the name in the controller matches the name on My Templates.

  • The request is forbidden. The Web API answers with status code 403 when the API key is wrong or deleted, when the document quota of the month is used up or when more than two requests of your account arrive at the same time. Compare the key with the list on Manage Account and check the quota on the dashboard of the portal.

  • The build reports vulnerable packages. NuGet audits the dependencies of the package and warns about Microsoft.NETCore.App 1.1.2, Microsoft.NETCore.Jit 1.1.2 and Newtonsoft.Json 10.0.3:

    warning NU1903: Package 'Newtonsoft.Json' 10.0.3 has a known high severity vulnerability, https://github.com/advisories/GHSA-5crp-9r3c-p9vr
    

    The package was last published in September 2019, and these are the dependencies of its .NET Core 1.1 build; a warning NETSDK1206 about runtime identifiers of the library Libuv comes from the same dependencies. Installing the current Newtonsoft.Json into your project with dotnet add package Newtonsoft.Json replaces version 10.0.3 and removes its warning. The warnings about Microsoft.NETCore.App and Microsoft.NETCore.Jit stay, and the application builds and runs with them.

Next Steps

  • Web API: the same kind of merge with curl, which shows the request the SDK sends.
  • .NET Framework: the SDK in an ASP.NET MVC 5 application, listing the templates of your storage.
  • Merge Data: how objects and arrays map to merge fields and merge blocks.
  • Merge Settings: remove empty fields and blocks, set document properties and the culture.
  • .NET: every method of the .NET SDK.