# ReportViewer Core: a .NET 6 port of the WinForms Report Viewer for existing RDLC reports

> ReportViewer Core is a C# port of Microsoft Reporting Services Report Viewer for .NET 6 and later, so existing RDLC reports and WinForms previews keep working on .NET Core. It suits a team migrating a business desktop application off .NET Framework, and the port is not supported by Microsoft and needs Wine for PDF rendering on Linux.

**lkosson/reportviewercore** — Recompilation of Microsoft.ReportViewer for .NET Core 3.1+

- Repository: https://github.com/lkosson/reportviewercore
- Stars: 568 · Forks: 164
- Language: C#
- License: not declared
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/lkosson-reportviewercore

## A port answering a gap Microsoft left open

ReportViewer Core is a port of Microsoft Reporting Services Report Viewer to .NET 6 and later. The readme describes it as feature-complete and ready for production use, with the caveat that it is not officially supported by Microsoft.

The reason the port exists is spelled out in the Why section, and it is a history of a promise not kept. With WinForms inclusion in .NET Core 3.1 and .NET 5 as a replacement for .NET Framework, it became feasible to port existing business desktop applications to .NET Core SDK to benefit from new C# and JIT features. The Microsoft team stated on multiple occasions, across several linked GitHub issues, that there are no plans to have an official Reporting Services or ReportViewer package for .NET Core, which was a showstopper for applications using this technology for printing and reporting.

So the goal of this project is to provide a transitional solution for such applications, until existing reports are reimplemented using more modern technology.

That last sentence sets the expectation properly. This is a bridge, and the author says so. The value is not that the port is better than the original but that it lets a large existing estate of RDLC reports keep working while the reports themselves are rewritten. A business application with a few hundred report definitions cannot be reimplemented in a quarter, and without a .NET Core ReportViewer it cannot even be recompiled.

The primary language is C#, the default branch is master, and the repository has no GitHub releases, so the version is whatever the packages give you rather than a tag you can pin. The last push was on 2026-08-29. The recorded licence is unknown, which for a project built from Microsoft source is worth thinking about before you ship it, and the CHANGELOG.md file at the top level is where version history and recent fixes are tracked.

The repository layout is organised by the original assemblies. Microsoft.ReportViewer.Common, Microsoft.ReportViewer.DataVisualization, Microsoft.ReportViewer.NETCore, Microsoft.ReportViewer.ProcessingObjectModel and Microsoft.ReportViewer.WinForms are the ported pieces, alongside five sample projects that between them cover every supported scenario.

## Swapping the reference in a WinForms project

For the case the port primarily targets, the migration is a reference swap rather than a rewrite.

You should be able to replace references to Report Viewer in your WinForms project with the ones provided in this repository and use Microsoft.Reporting.WinForms.ReportViewer as usual. The namespace is preserved, so the code that instantiates the control, sets its report source and handles the events does not change.

The samples show the two processing modes separately. ReportViewerCore.Sample.WinForms is the simplified example using local report processing, where the RDLC definition and the data are both in the client application. ReportViewerCore.Sample.WinFormsServer is the remote processing example using a Reporting Services server, where the report definition and execution live on the server and the control acts as a viewer over it.

That distinction is the one to get right when you plan the migration, because it decides where your work goes. A local report is compiled and rendered in the client process, so a data-processing change to the report definition is a code change in your application. A remote report is executed by the Reporting Services server, so the same report definition behaves differently and your existing server-side infrastructure does the work.

The readme is careful to state the mode in each sample name, which is a small thing that saves a lot of confusion, because a report that renders locally can fail in a server context and vice versa for reasons that have nothing to do with the port itself.

The WinForms preview is listed under what works, together with RDLC file loading and compiling, local data sources, parameter passing, all rendering formats including PDF and XLS, remote processing using Reporting Services, Linux and MacOS support, and the MSChart control. That last entry matters more than it looks, because the chart control is a separate native Windows dependency in the original stack.

## Rendering a report from ASP.NET Core or a console app

The ASP.NET Core story is different from the WinForms one, and it is the case where the port does the most work for you.

For ASP.NET Core applications, you add a reference to Microsoft.Reporting.NETCore, which is based on the WinForms version with a stripped UI, and you load and render the report programmatically. The readme gives this as a starting point.

```csharp
    Stream reportDefinition; // your RDLC from file or resource
    IEnumerable dataSource; // your datasource for the report
    
    LocalReport report = new LocalReport();
    report.LoadReportDefinition(reportDefinition);
    report.DataSources.Add(new ReportDataSource("source", dataSource));
    report.SetParameters(new[] { new ReportParameter("Parameter1", "Parameter value") });
    byte[] pdf = report.Render("PDF");
```

Five lines of real work. You create a LocalReport, load the RDLC definition from a stream, add a data source under a name, set parameters, and render. The output is a byte array, which is what a web endpoint returns.

The remote equivalent uses ServerReport and goes through the server's URL and credentials.

```csharp
    ServerReport report = new ServerReport();
    report.ReportServerCredentials.NetworkCredentials = new NetworkCredential("login", "password", "DOMAIN");
    report.ReportServerUrl = new Uri("http://localhost/ReportServer");
    report.ReportPath = "/Invoice";
    report.SetParameters(new[] { new ReportParameter("Date", DateTime.Now.Date.ToString()) });
    byte[] pdf = report.Render("PDF");
```

The NetworkCredential constructor takes the domain as its third argument, so the domain is part of the identity rather than being embedded in the URL.

What this path does not give you is an interactive viewer. There is no interactive, web-based report viewer provided in this project. The two web rendering formats are HTML4.0 and HTML5, and the HTML5 format has been modified to also work without JavaScript. ReportViewerCore.Sample.AspNetCore is the demo for that. The practical shape is that a report is rendered on request and returned, and the user sees a document rather than a report viewer with export buttons, parameter prompts and a tree of the report's groups.

## Rendering formats, and the Wine problem on Linux

The rendering format list is complete rather than partial, and the asterisks on it are the interesting part.

All formats are supported on Windows, Linux and Mac OS. For the formats marked with an asterisk, there is a workaround section to read. The list covers HTML4.0, HTML5 and MHTML; PDF with an asterisk; IMAGE in TIFF and EMF with an asterisk; EXCEL in the Microsoft Excel 97/2003 format with an asterisk and EXCELOPENXML without one; WORD in the Microsoft Word 97/2003 format with an asterisk and WORDOPENXML without one; plus CSV and XML.

The reason for the asterisks is a font measurement dependency. Some rendering formats, most notably PDF, use Windows-provided native libraries for font measurements, Uniscribe, which are unavailable on other platforms. They are, however, provided in barely working condition by Wine, version 5.0 or higher. To export reports to PDF, TIFF or XLS you need Wine 5.0 or newer, and the readme notes that for Debian Bullseye, apt install wine will do.

The steps that follow are specific rather than approximate. Download the Windows version of .NET runtime binaries from the Microsoft download site, for example the .NET 3.1.30 windows x86 binaries package. Extract those binaries to a local folder such as ~/dotnet-3.1-windows. Then start your application using the 64-bit version of Wine and the Windows version of .NET, in the form wine64 ~/dotnet-3.1-windows/dotnet.exe YourApplication.dll.

There is a failure mode named explicitly. If your application crashes with unsupported flags 00000020 somewhere inside bcrypt, make sure you have a proper version of Wine installed, because version 4.1, provided in Debian Buster and earlier, will not work.

So on Linux, exporting a PDF means running your .NET application under Wine against a Windows .NET runtime, purely to get the font measurement libraries. That is a substantial constraint, and it is the kind of thing that is invisible until the first PDF export on a Linux build agent.

The readme points at the way out. For fully native cross-platform support, see NicFT's fork, RdlCore. That is the honest recommendation for anyone whose deployment target is Linux and whose output format is PDF.

## Designing new reports, and the .xsd workaround

If you are not just porting existing reports but also creating new ones, the toolchain is where the friction is.

Visual Studio 2019, version 16.9 and similar, does not include Report Designer by default. An extension provided by Microsoft called Microsoft RDLC Report Designer has to be installed to open and modify reports. For Visual Studio 2022 the corresponding extension is Microsoft RDLC Report Designer 2022.

Then there is the dataset wizard problem, and the workaround is the most unusual piece of the whole project. Even after installing the extension, the new dataset wizard fails to show classes from your project, and .NET Core projects do not have .datasource file support either. The workaround is to create and add an .xsd file to your project with definitions of the types you want to use in your reports.

The readme gives a snippet that produces such a file for all the classes you need.

```csharp
    var types = new[] { typeof(ReportItemClass1), typeof(ReportItemClass2), typeof(ReportItemClass3) };
    var xri = new System.Xml.Serialization.XmlReflectionImporter();
    var xss = new System.Xml.Serialization.XmlSchemas();
    var xse = new System.Xml.Serialization.XmlSchemaExporter(xss);
    foreach (var type in types)
    {
        var xtm = xri.ImportTypeMapping(type);
        xse.ExportTypeMapping(xtm);
    }
    using var sw = new System.IO.StreamWriter("ReportItemSchemas.xsd", false, Encoding.UTF8);
    for (int i = 0; i < xss.Count; i++)
    {
        var xs = xss[i];
        xs.Id = "ReportItemSchemas";
        xs.Write(sw);
    }
```

The mechanism is that the schema exporter walks the type list and writes a schema file, and the schema id is set to ReportItemSchemas so that Report Designer sees a datasource with that name. After including the ReportItemSchemas.xsd file in your project, Report Designer should see a new datasource called ReportItemSchemas which you can use to add a dataset to your report.

The workflow consequence is that the types a report can bind to are declared in a generated XML schema rather than discovered from the project, which means the schema file has to be regenerated when your report model changes. For a project with a stable model that is a one-off step; for a project with a frequently changing one it is a piece of maintenance the original .NET Framework toolchain did not require.

## What does not work, and where the real alternatives are

The readme has a section on what does not work, and it is short enough to quote in full because each item changes a decision.

Spatial SQL types do not work. Those require the Microsoft.SqlServer.Types package, which is available only in .NET Framework, so reports using SqlGeography will not load.

Expression sandboxing and code security do not work either, with the instruction: do not load and run reports from untrusted sources. That is the most consequential line in the readme, and it should govern where you put this component. A report definition can contain expressions that the processing engine evaluates, and in the original stack those ran inside the Report Viewer sandbox. Without that sandbox, a report is code running in your process with the permissions of your application. So any deployment where users upload report definitions and you render them is out of scope, regardless of how good the port is.

Interactive web report preview does not work, and the reason given is that it is closely tied to WebForms. That is the boundary of the port: the WinForms control is reproduced, the WebForms-era interactive viewer is not, and the web path is render-and-return.

The comparison with the alternatives follows from those limits. The first alternative is staying on .NET Framework, which is the thing the project exists to let you leave, and it works but forfeits the new C# and JIT features the port was for. The second is rewriting the reports in a modern technology, which the readme names as the eventual goal, and which is the right answer for a new report but not for several hundred existing ones. The third is NicFT's RdlCore fork, which the readme points at for fully native cross-platform support, and which is the answer to the Wine constraint.

There is also the licensing question. The recorded licence is unknown, and the project is a port of Microsoft Reporting Services code. Before you put it in a shipped product, you need to know what the terms are, and that is a question for whoever owns the repository, not something the readme answers.

## Conclusion

ReportViewer Core fits a team with a large body of existing RDLC reports on .NET Framework that cannot migrate because Microsoft never shipped a .NET Core ReportViewer, and it does not fit a greenfield reporting project, since designing new reports still needs the Microsoft RDLC Report Designer extension and the .xsd workaround. Before committing, check the changelog for version history and fixes, and read the section on what does not work, because spatial SQL types and expression sandboxing are not supported and reports from untrusted sources must not be loaded.

## FAQ

### What is ReportViewer Core and why was it created?

It is a port of Microsoft Reporting Services Report Viewer to .NET 6 and later, created because Microsoft stated on several occasions that there are no plans to ship an official ReportViewer package for .NET Core, which blocked porting business desktop applications off .NET Framework.

### How do I use ReportViewer Core in an ASP.NET Core application?

Reference Microsoft.Reporting.NETCore, which is based on the WinForms version with a stripped UI, then create a LocalReport, load the RDLC definition, add a ReportDataSource, set parameters and call Render with the format you want. The result is a byte array you return from the endpoint.

### Does ReportViewer Core render PDF on Linux without extra setup?

Not natively. Some formats, most notably PDF, use Windows-provided native libraries for font measurements which are unavailable elsewhere, so the readme requires Wine 5.0 or higher and Windows .NET runtime binaries to export PDF, TIFF or XLS. It points at NicFT's RdlCore fork for fully native cross-platform support.

### What are the security limits of ReportViewer Core?

Expression sandboxing and code security are not provided, so reports from untrusted sources must not be loaded and run. Reports using SqlGeography will also not load, because the spatial SQL types require a package available only in .NET Framework.

## Sources

- [Issues](https://github.com/lkosson/reportviewercore/issues)
- [lkosson/reportviewercore on GitHub](https://github.com/lkosson/reportviewercore)
- [README](https://github.com/lkosson/reportviewercore/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/lkosson-reportviewercore
