The repository includes two libraries and a runnable integration example:
NextgenReports.Client: HTTP session, JSON/.NET object input, SVG preview, layout JSON, explicit data refresh, PDF/HTML/XLSX/DOCX download and structured errors.NextgenReports.Blazor: an Interactive Server component with page navigation, zoom, cancellation, export controls, both Office modes and loading/error states.examples/BlazorDemo: local application demonstrating the complete workflow.
The report engine runs in Studio/server. Neither library embeds a native rendering engine in the browser. WebAssembly/Auto modes and mobile/offline execution are not implemented or verified by this integration. The separate Linux desktop shell hosts Studio. Flutter is covered by the separate Flutter/Dart SDK guide.
Run the example
Use .NET 10. Start Studio using the normal instructions. In another terminal, from the repository root:
dotnet run --project examples/BlazorDemo --urls http://127.0.0.1:5277Open http://127.0.0.1:5277 in Chrome. The demo uses
http://127.0.0.1:5274/ as its report server. Override it using the
ReportServer configuration key, for example:
ReportServer=https://reports.example.test/ dotnet run --project examples/BlazorDemo --urls http://127.0.0.1:5277- With a local-mode Studio, the example immediately shows 65 sample equipment rows over multiple pages. With server accounts enabled, sign in as Author/Admin.
- Use Next / Previous, then Zoom. Navigation uses the already generated SVG pages and does not call the report engine again.
- Change Company and Rows, then Apply data. Expect a new first page, a reset page position and the updated page count. Row count is limited to 1–300 in this example. The input data comes from ordinary C# objects.
- Choose PDF, HTML, Excel or Word, then Download. For Office, choose Editable or Exact pages. The downloaded file uses the last successfully generated input, not unsubmitted form edits.
- Enable Demonstrate report error and apply. Expect an English validation message and no stale preview or downloadable file. Clear it and apply to recover.
The demo accepts only loopback connections with a loopback Host header. It is a learning application, not a published multi-user portal. Its login talks to the report server; it does not implement application-level identity, report ownership or access rules. Each interactive circuit owns its own client/cookie jar.
Linux desktop launcher
Install the desktop entry for this checkout:
python3 scripts/install-demo-launcher.pyDouble-click Nextgen Reports Demo on the desktop. It starts Studio on 5274 and the Blazor demo on 5277 if they are not already available, then opens both the demo and the built-in developer guide with code examples in a visible Chrome window. Existing browser tabs are preserved. Right-click actions Open demo and Open documentation open only the selected page. If GNOME asks, choose Allow Launching. The installer sets the executable bit and GNOME trust metadata when available.
The launcher uses this checkout's Release build; if missing, it builds the solution.
After changing source code, rebuild before reopening the demo. Processes stay
running after Chrome closes so subsequent launches can reuse them. Startup logs
are under artifacts/launcher/. Required commands: dotnet, curl, python3, flock,
setsid and google-chrome; zenity shows startup errors when installed.
bash scripts/open-demo.sh --start-only starts/reuses the processes without opening
Chrome. The right-click menu also offers Open Flutter demo; see the Flutter guide.
No system service or automatic login startup is installed. If the checkout
moves, run the installer again; delete the desktop entry to remove the launcher.
The local launcher is Linux-specific and does not configure remote server hosting.
Use the HTTP client
Add a project reference to src/NextgenReports.Client/NextgenReports.Client.csproj.
No PDF, database, browser or third-party NuGet dependency is needed by this client.
using System.Text.Json;
using NextgenReports.Client;
using var client = ReportClient.Create(new Uri("http://127.0.0.1:5274/"));
var session = await client.GetSessionAsync(cancellationToken);
if (session.Enabled)
await client.LoginAsync(userName, password, cancellationToken);
using var template = JsonDocument.Parse(File.ReadAllText("report.nrtemplate"));
var input = ReportInput.FromObjects(template.RootElement,
new { items = new[] { new { Name = "Chair", Amount = 42.25m } } },
new { company = "Example company" });
var file = await client.ExportAsync(input, ReportFormat.Pdf, token: cancellationToken);
await File.WriteAllBytesAsync("report.pdf", file.Content, cancellationToken);The template must declare the company parameter and bind the fields Name and
Amount with matching case. FromObjects preserves default .NET property names;
pass your own JsonSerializerOptions only if you also use the corresponding names
in the template. No SQL/HTTP refresh happens implicitly.
For existing JSON, construct new ReportInput(templateJson, dataJson, parametersJson).
The constructor clones all JSON elements, so their source JsonDocument can be
disposed. Template/data must be objects; parameters must be an object or omitted.
Treat each input as a snapshot and construct a new one after editing values.
Other operations:
var preview = await client.PreviewAsync(input, cancellationToken);
// preview.Pages: numbered SVG bytes and a data URL; one render for the entire report.
var layout = await client.PreviewDocumentAsync(input, cancellationToken);
// JsonElement containing the full ReportDocument protocol, including drawing commands.
var refreshed = await client.RefreshDataAsync(input, cancellationToken);
var updated = new ReportInput(input.Template, refreshed.GetProperty("data"), input.Parameters, useSnapshot: true);
var word = await client.ExportAsync(updated, ReportFormat.Docx,
new ReportExportOptions(OfficeMode.Pages, FirstPage: 1, LastPage: 2, Dpi: 150),
cancellationToken);RefreshDataAsync uses the host's configured sources and returns a candidate
snapshot; explicitly construct a new input to use it. Credentials and connection
strings remain in the host catalog. See data sources.
ReportExportOptions applies only to Office; PDF and HTML export the whole report.
Handle ReportApiException: StatusCode, Message, and optional
ParameterErrors (the server's JSON structure) retain validation and role errors.
401 requires a fresh login; 403 can mean permissions or an invalid CSRF token.
The client never automatically replays a failed POST or stores your password.
Transport errors use HttpRequestException; cancellation/timeouts use
OperationCanceledException; invalid/oversized responses use InvalidDataException
or JsonException. Dispose the client when its user session ends.
Add the Blazor component
Add a project reference to src/NextgenReports.Blazor/NextgenReports.Blazor.csproj.
Register one client per interactive circuit, not a singleton or pooled shared
cookie handler:
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
builder.Services.AddScoped(_ => ReportClient.Create(new Uri(reportServerUrl)));Configure Interactive Server rendering in the host as shown in the example. Include the library stylesheet in the host document:
<link rel="stylesheet" href="_content/NextgenReports.Blazor/viewer.css" />Then render it on an interactive page:
@using NextgenReports.Client
@using NextgenReports.Blazor
@inject ReportClient Client
<ReportViewer Client="Client" Input="input" OnLoaded="Loaded" OnError="Failed" />
@code {
private ReportInput? input;
private void Loaded(int pages) { /* Update your application status. */ }
private void Failed(string message) { /* Show or record an application error. */ }
}Your host supplies the input, parameter form and login flow. The component does not
reproduce Studio's designer, parameter-dialog scripts, search or drill-down. Assign
a new input object to trigger regeneration. Generate reruns the current input;
Cancel stops waiting and sends request cancellation. Disposal and replacement
inputs cancel outstanding work; a stale request cannot replace a newer preview.
@ref callers may also await ReloadAsync().
The download JavaScript module is imported from
_content/NextgenReports.Blazor/viewer.js. Configure static web assets in the host
(the runnable example includes this). Allow same-origin JS and data: images in
any host CSP. CSS uses .nr-* classes and optional variables --nr-text,
--nr-background, --nr-control, --nr-border, --nr-canvas, --nr-muted,
--nr-error for application theming.
Limits and deployment
ReportClient.Createuses an isolated CookieContainer, disabled redirects and a three-minute HttpClient timeout. HTTPS is required except for loopback HTTP. Custom HttpClient callers must provide equivalent cookie/redirect isolation; the constructor does not own that client unlessownsHttpClient: trueis set.- Author/Admin may generate from submitted input. Viewer accounts cannot use POST generation APIs; use Studio's saved reports/scheduled downloads for those users.
- Preview is one SVG archive, at most 100 pages, 25 MB per SVG and 100 MB expanded. All successful responses are bounded to 100 MB by the client; error bodies to 64 KB. Pages are kept in memory. Large reports should use direct PDF export.
- Preview SVG has outlined text: it looks like the engine output but is not a selectable-text or screen-reader transcript. Page navigation has text labels; use editable Office/HTML output when the underlying text is needed.
- Download regenerates from the successful input snapshot. Time-dependent scripts can differ from the preview. Opted-in HTTP connections refresh on each request unless ReportInput uses useSnapshot:true; use a refreshed input with that flag for matching preview/download.
- Cancellation is cooperative; it cannot reverse work already completed by the host.
- A local-mode Studio grants local callers generation access. In your own remotely accessible app, authenticate and authorize users before invoking it; use server accounts/HTTPS for remote Studio. Do not expose the demo as an open proxy.
- Verified on Linux/iMac with Interactive Server and visible Chrome. WebAssembly, macOS, Windows, remote HTTPS deployment and package-registry publication are not verified. Libraries are consumed from this repository; no NuGet release was made.
Razor library asset handling follows Microsoft's RCL documentation.
Downloads use DotNetStreamReference and an object URL as described in
Blazor file downloads.
For automatic HTTP sources, PreviewDocumentAsync returns sourceSnapshot after
a successful refresh. Construct new ReportInput(input.Template, layout.GetProperty("sourceSnapshot"), input.Parameters, useSnapshot: true) to
reuse it for exports. ReportInput.FromObjects also accepts useSnapshot. The
flag defaults to false and affects automatic refresh only; RefreshDataAsync remains
an explicit fetch. See the HTTP guide.