C# in.
Reports out.

An open-source RDL engine for .NET 8 & 10. PDF, Excel, HTML, CSV and more — from SQL, JSON, or pure C#. MIT licensed.

$ dotnet add package Majorsilence.Reporting.RdlEngine.SkiaSharp
Program.cs in
var parser = new RDLParser(rdlXml);
using var report = await parser.Parse();
await report.RunGetData(null);
await report.RunRender(ofs,
  OutputPresentationType.PDF);
report.pdf out
Sales Summary — Q2 2026
Generated 2026-06-11 · page 1 of 4
RegionUnitsRevenue
North America12,408$1.24M
Europe9,112$0.97M
Asia-Pacific7,654$0.81M
Total29,174$3.02M
PDF XLSX HTML CSV XML TIFF MHT
7+
Output formats
10+
Data sources
10
Barcode / QR types
.NET 8 & 10
Cross-platform
MIT
Open source

Everything you need for .NET reporting

From simple PDF invoices to complex multi-page reports with barcodes, charts, and dynamic data — all from a single library.

📄

Multi-Format Export

Render any report to PDF, Excel (xlsx), HTML, CSV, RTF, and XML from a single data fetch. One call, every format.

PDF XLSX HTML CSV RTF
🗄️

Flexible Data Sources

Connect to SQLite, SQL Server, PostgreSQL, MySQL, Firebird, JSON files, XML, or inject data directly from C# objects.

Microsoft.Data.Sqlite · Json · SQL · PostgreSQL
📦

Barcode & QR Codes

10 built-in CRI barcode types via ZXing.Net: QR Code, Code 128, Code 39, Data Matrix, Aztec, PDF417, ITF-14, and more.

Custom Report Items (CRI)
🖥️

Visual Designer

Drag-and-drop report designer on Windows. Design RDL files visually, then render them server-side on any OS.

Windows Designer · Cross-Platform Render
🌐

Cross-Platform

Server-side rendering runs on Linux, macOS, and Windows. Works great in Docker containers and cloud deployments.

Linux · macOS · Windows · Docker

RDL Report Format

Based on the open RDL (Report Definition Language) standard. Reports are XML files — version-control friendly and portable.

Open Standard · XML · Portable

Add to your project

Available on NuGet. Add the engine, then optionally the CRI package for barcode support.

$ dotnet add package Majorsilence.Reporting.RdlEngine.SkiaSharp
$ dotnet add package Majorsilence.Reporting.RdlCri.SkiaSharp
$ dotnet add package Majorsilence.Reporting.RdlCreator.SkiaSharp

Up and running in minutes

Call RdlEngineConfigInit() once at startup, load an RDL file, and render to any format.

Render a SQLite-backed report to PDF C#
using Majorsilence.Reporting.Rdl;

// Call once per application instance
RdlEngineConfig.RdlEngineConfigInit();

var baseDir = AppContext.BaseDirectory;
var dbPath  = Path.Combine(baseDir, "mydata.db");
var outPath = Path.Combine(baseDir, "report.pdf");

var rdlXml = (await File.ReadAllTextAsync("Report.rdl"))
    .Replace("mydata.db", dbPath);

var parser = new RDLParser(rdlXml) { Folder = baseDir };
using var report = await parser.Parse();

await report.RunGetData(null);
var ofs = new OneFileStreamGen(outPath, true);
await report.RunRender(ofs, OutputPresentationType.PDF);
Export to PDF, Excel, CSV, and HTML in one pass C#
// RunGetData once, then RunRender for each format.
await report.RunGetData(null);

foreach (var (filename, format) in new[] {
    ("report.pdf",  OutputPresentationType.PDF),
    ("report.xlsx", OutputPresentationType.Excel2007),
    ("report.csv",  OutputPresentationType.CSV),
    ("report.html", OutputPresentationType.HTML),
}) {
    var ofs = new OneFileStreamGen(filename, true);
    await report.RunRender(ofs, format);
}
Read data from a local JSON file RDL + C#
/* In the RDL DataSource */
<ConnectionProperties>
  <DataProvider>Json</DataProvider>
  <ConnectString>file=employees.json</ConnectString>
</ConnectionProperties>

var rdlXml = (await File.ReadAllTextAsync("Employees.rdl"))
    .Replace("employees.json", Path.Combine(baseDir, "employees.json"));

var parser = new RDLParser(rdlXml) { Folder = baseDir };
using var report = await parser.Parse();
await report.RunGetData(null);
await report.RunRender(new OneFileStreamGen("out.pdf", true), OutputPresentationType.PDF);
Add a QR Code or barcode to a report (CRI) RDL + C#
/* QrCode · BarCode128 · BarCode39 · DataMatrix · AztecCode · Pdf417 · ITF-14 */
<CustomReportItem Name="ProductQR">
  <Type>QrCode</Type>
  <CustomProperties>
    <CustomProperty>
      <Name>Code</Name>
      <Value>=Fields!ProductName.Value</Value>
    </CustomProperty>
  </CustomProperties>
</CustomReportItem>

var parameters = new Dictionary<string, string>
    { ["BarcodeType"] = "DataMatrix" };
await report.RunGetData(parameters);
Inject data from C# objects instead of a live query C#
record SaleRecord(string Product, string Region, decimal Amount, int Quantity);

var salesData = new List<SaleRecord>
{
    new("Widget A", "North", 1250.00m, 50),
    new("Widget B", "South", 840.50m,  33),
};

await report.DataSets["Data"].SetData(salesData);
await report.RunGetData(null);
await report.RunRender(ofs, OutputPresentationType.PDF);