DEV Community

Cover image for How to Bind Data in an RDL or Page Report Using C# .NET
Chelsea Devereaux for MESCIUS inc.

Posted on • Originally published at developer.mescius.com

How to Bind Data in an RDL or Page Report Using C# .NET

What You Will Need

  • ActiveReports.NET
  • Visual Studio

Controls Referenced

Tutorial Concept

This tutorial provides a step-by-step guide on how to programmatically bind data to RDL or Page Reports using .NET with ActiveReports.NET. It covers designing reports with mock data and replacing them with actual data at runtime, focusing on key concepts like the LocateDataSource event for runtime data binding.


Data binding establishes a connection between a report and the data it displays. ActiveReports.NET allows you to bind data at design time, but there are times when you need to bind data at run time, for example:

  • You use a database, such as MongoDB, that is not supported for binding at design time.
  • Your application has an existing data layer implementation that you want to reuse for report data binding.

To support these scenarios, ActiveReports.NET provides the ability to bind data at runtime. This article suggests a simple framework for designing reports using mock data at design time and replacing them with the actual data at runtime. The described procedures only apply to binding data in RDL and Page Reports.

In this blog, we will break down data binding reports using C# throughout the sections below:

Use Case

Suppose you are working on a call center software that provides a monthly performance report to a manager. For example, the manager needs to know the number of calls received by each employee, the number of answered calls, the average call duration, and the resolution rate. The UX team provided the report design, including colors, fonts, and formatting. Here is an example of such a report:

Bind Data RDL Using .NET

The application's data layer queries the data source for call records obtained from a given period, and the result is the list of objects shown below:

    public class CallRecord
    {
        /// <summary>
        /// Gets or sets the start date of the call
        /// </summary>
        public DateTime StartDate { get; set; }
        /// <summary>
        /// Gets or sets duration of the call in seconds
        /// </summary>
        public float Duration { get; set; }
        /// <summary>
        /// Gets or sets the name of agent handling the call
        /// </summary>
        public string AgentName { get; set; }
        /// <summary>
        /// Gets or sets the value indicating whether the call was answered
        /// </summary>
        public bool Answered { get; set; }       
        /// <summary>
        /// Gets or sets the value indicating whether the call was resolved
        /// </summary>
        public bool Resolved { get; set; }
    }
Enter fullscreen mode Exit fullscreen mode

The data layer interface is as follows:

    public interface IDataLayer
    {
        IEnumerable<CallRecord> GetPerformanceData(DateTime startDate, DateTime endDate);
    }
Enter fullscreen mode Exit fullscreen mode

Designing a Report

First, you must design a report according to the UX guidelines. To do that, you don't need to access the actual data. It is convenient to use mock data to quickly switch between the report design and its output in the Visual Studio Integrated Designer without having to run your application to generate the report output.

ActiveReports.NET supports the CSV data provider that you can use to bind a report to mock data. To generate simulated data, you can use any available CSV data generator, for example, the one from extendclass. Once the data are ready, you can save them into a local file. For example, the following snippet shows the fragment of such a file.

StartDate Duration AgentName Answered Resolved
2021-01-28 110.68 Greg False True
2021-01-22 15.14 Jim True True
2021-01-28 20.17 Jim False True
2021-01-20 44.8 Martha False False

To create a new report that is bound to the mock data, follow the steps below:

  1. In Visual Studio, open your project.
  2. Add a new ActiveReports 17 RDL Report or ActiveReports 17 Page Report to the project.
  3. Open the Report Explorer.
  4. Add a new Data Source, select the CSV Provider in the Type dropdown of the data source dialog, and click the Edit icon in the toolbar of the Connection String editor.
  5. Click the Open button and choose the CSV file containing the mock data.
  6. Click the Get from Preview button. The dialog populates the column list automatically.
  7. Set the data type for each column and click the OK button.

Configure CSV Data Source

The report designer will automatically create the new DataSet and populate its fields. So now you can design the report, check its output in the Preview tab, return to the Design tab, adjust as necessary, and so on.

Supplying the Data at Runtime

In the actual application, the data comes from the data layer that returns the CallRecord object list. ActiveReports.NET offers the Object data provider that accepts any object that implements the IEnumerable interface as the input. So, the first thing you need to do is modify the report's data source type.

  1. In Visual Studio, make sure that the report is opened.
  2. In the Report Explorer, select the data source item and click the Edit button.
  3. Select Object Provider in the Type dropdown and click the OK button.
  4. Save the changes.

If you preview the report in the Preview tab, you will see that it shows the error message:

GrapeCity.ActiveReports.ReportException: An unexpected error occurred. Additional information: 'No data has been set. Please specify IEnumerable to use

The application code should provide the data for the Object data provider in the LocateDataSource event handler. For example, the following code loads the report definition from the application resources, adds the LocateDataSource event handler, and exports the report output to a PDF document, saving it in the memory.

    internal System.IO.Stream GenerateReportOutput(IDataLayer dataLayer, System.DateTime startDate, System.DateTime endDate)
    {
        using (var reportStream =GetType().Assembly.GetManifestResourceStream("RuntimeDataBinding.CallCenterPerformace.rdlx"))
        using (var reader = new System.IO.StreamReader(reportStream))
        {
            var rpt = new GrapeCity.ActiveReports.PageReport(reader);
            var pdfRe = new GrapeCity.ActiveReports.Export.Pdf.Page.PdfRenderingExtension();
            var output = new GrapeCity.ActiveReports.Rendering.IO.MemoryStreamProvider();
            rpt.Document.LocateDataSource += (sender, args) =>
            {
                args.Data = dataLayer.GetPerformanceData(startDate, endDate);
            };
            rpt.Document.Render(pdfRe, output);
            return output.GetPrimaryStream().OpenStream();
        }
    }
Enter fullscreen mode Exit fullscreen mode

LocateDataSource Event

The LocateDataSource event is the foundation of the runtime data binding. The event handler is called by the report engine when the report needs to obtain the data. The event handler should set the Data property of the LocateDataSourceEventArgs instance to the data object that the report will use as the data source. Several data providers support runtime data binding. The following table shows the list of these data providers along with the acceptable data types and conditions for LocateDataSource occurrence.

Data providers

The LocateDataSourceEventArgs instance that is passed to the event handler also exposes the following useful properties when the same LocateDataSource handler is called for several reports. For instance, if a report contains a subreport, then the LocateDataSource event handler will be called for each subreport instance in addition to the main report.

Useful properties

Finally, if you use the JSViewer and want to supply the data at runtime, then the LocateDataSource event handler is set on for the UseReporting middleware, for example:

    app.UseReporting(settings =>
    {
        settings.SetLocateDataSource((args) =>
        {
            var startDate = (DateTime)args.Parameters[0].Value;
            var endDate = (DateTime)args.Parameters[1].Value;
            return _dataLayer.GetPerformanceData(startDate, endDate);
        });
    });
Enter fullscreen mode Exit fullscreen mode

Conclusion

In conclusion, binding data in RDL and Page Reports using C# streamlines the process of generating dynamic reports at runtime. By leveraging mock data during the design phase and replacing it with actual data at runtime, developers can ensure that their reports are accurate and up-to-date without needing extensive redesigns. This approach is particularly useful when data sources are not supported at design time or when reusing existing data layers. With the LocateDataSource event, developers can efficiently bind various data types, making ActiveReports.NET a versatile tool for robust reporting solutions.


Top comments (0)