Search code examples
c#winformsrdlcreportviewer.net-8.0

Issue adding a data source with Microsoft RDLC Report Designer in a C# WinForms app under .Net 8.0


I am trying to add some basic reporting into a .Net 8.0 C# WinForms app using the Microsoft RDLC Report Designer and the ReportViewerCore.WinForms nuget package, and have found myself running into a number of issues.

Does anyone have any experience of getting this to work, and getting past these problems?

The steps I have undertaken so far are:

  • Install the Microsoft RDLC Report Designer extension (17.0.0) into Visual Studio Enterprise 2022 (17.10.0)
  • Install the ReportViewerCore.WinForms nuget package (15.1.19) into my WinForms project (this required me to first install Microsoft.CodeAnalysis.Common v4.8.0, which is not the current version)
  • Add a new report into the WinForms project
  • In the "Report Data" window, select the "New" dropdown, and "Dataset..."
  • Select "Object" in the "Choose a Data Source Type" dialog
  • Select a model class from my business model project. Note that, at this point, no classes from the same assembly (my WinForms assembly) are listed, however, this is not an issue for me.
  • When picking any class as an object data source, I am presented with the following unhelpful error message:

enter image description here

  • In order to try to determine whether it is something I have done specifically with my model classes that is causing the issue, I then created a fresh solution, with nothing other than a WinForms project and a class library project, and repeated this process, creating an absolutely basic POCO class with one int property. This had the same issue. However, I found that if I extracted an interface for that class, and chose the interface as the data source, then this would work. I then tried this in my original solution, and again, this worked:
 public class Class1 : IClass1
 {
     public int MyProperty { get; set; }
 }
 public interface IClass1
 {
     int MyProperty { get; set; }
 }
  • Having found that extracting the interface for a class seems to work, I then did the same for one of my more complex model classes, and attempted to add this as a data source. I then get the following error (class name redacted):

enter image description here

  • I then went back to my simple Class1 class, added a string property to it, recompiled, and attempted to remove and re-add this as a data source, to get the same error here.

My conclusion is that there seems to be some sort of issue with the report designer being able to determine the CLR types in the class, extracting an interface goes some way towards mitigating this, but the underlying problem could be that the designer, specifically the "Data Source Configuration Wizard" appears to be trying to use the wrong version of the System.Runtime assembly.

I've tried to work out whether dropping the correct system runtime DLL into the installation folder for the extension would work to solve this, but have been stymied by being unable to work out where the extension has actually been installed, and also which DLL I should copy into this location, if I can work out where to put it.

Searching here for this problem shows that others have had a similar issue in the past, but I can't find any solution that solves my specific issue. I have also tried using the older versions of the ReportViewer nuget packages, targeting .Net Framework, and these give me the exact same results.

If I have to extract interfaces for any POCOs I want to use for reports, I can live with this. However, if I am unable to use any complex types (such as objects that contain lists of other objects) for reporting, this will be a show-stopper.


Solution

  • As explained in the README of the ReportViewerCore.WinForms repository the new dataset wizard fails when trying to discover classes from the project. The official workaround is to add a ".xsd" file with the schema of the classes to your project.

    A code sinppet to produce the ".xsd" needed files automatically is provided in the repo. You have to change the "types" array to include the classes you want to use:

    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);
    }
    

    I you use ".xsd" files everything should work.

    You have all the information in the Designing new reports section of the repository.