Search code examples
c#.netwebformsrdlc

C# WebForms RDLC Report | Data source instance was not provided for the dataset


I'm creating a C# reporting solution consisting of multiple RDLC reports, and an ASPX view page behind each RDLC file, and the reports are fed with data from a local dataset (.xsd). the dataset contains both table adapters that retrieve data from SQL stored procedures and Datatables. Some reports need to obtain the data dynamically and use DataTable objects as data sources to be bound with the RDLC file. I'm following these steps

1- Create DataTable object in xsd dataset
2- Add a dataset to the RDLC report, with the type of the create DataTable in the xsd dataset.
3- In the code-behind ASPX file, retrieve the data in an IEnumerable object
4- Create an instance of the DataTable class created in (1), and add rows to the instance from the IEnumerable
5- Create a ReportDataSource object from the DataTable object with the name of the dataset specified in the RDLC report
6- add the ReportDataSource object to the DataSource collection of the report viewer.

.xsd dataset name: WoqodEPIDataSet.xsd
RDLC name: JobCardsReport.rdlc

Despite all that im still getting the error "A data source instance has not been supplied for the data source 'JobCards'."

the RDLC source code (DataSource and DataSet sections)

<?xml version="1.0" encoding="utf-8"?>
<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
  <AutoRefresh>0</AutoRefresh>
  <DataSources>
    <DataSource Name="WoqodEPIDataSet">
      <ConnectionProperties>
        <DataProvider>System.Data.DataSet</DataProvider>
        <ConnectString>/* Local Connection */</ConnectString>
      </ConnectionProperties>
      <rd:DataSourceID>e747194e-5f0b-4c76-8a8c-1739db95ceef</rd:DataSourceID>
    </DataSource>
  </DataSources>
  <DataSets>
    <DataSet Name="JobCards">
      <Query>
        <DataSourceName>WoqodEPIDataSet</DataSourceName>
        <CommandText>/* Local Query */</CommandText>
      </Query>
      <Fields>
        <Field Name="Time">
          <DataField>Time</DataField>
          <rd:TypeName>System.String</rd:TypeName>
        </Field>
      </Fields>
      <rd:DataSetInfo>
        <rd:DataSetName>WoqodEPIDataSet</rd:DataSetName>
        <rd:SchemaPath>C:\Users\OBA021\source\repos\APCReports\APCReports\WoqodEPIDataSet.xsd</rd:SchemaPath>
        <rd:TableName>dt_JobCards</rd:TableName>
        <rd:TableAdapterFillMethod />
        <rd:TableAdapterGetDataMethod />
        <rd:TableAdapterName />
      </rd:DataSetInfo>
    </DataSet>
  </DataSets>

code-behind ASPX:

    public partial class JobCardsReport : System.Web.Mvc.ViewPage {
        protected async Task Page_Load(object sender, EventArgs e) {
            if (!IsPostBack) {

                //retrieve station data
                StationDataModel station = StationDataProcessor.RetrieveStationData();
                Session["StationNo"] = station.StationNo;
                Session["StationName"] = station.StationName;

                //assign report parameters
                var repParams = new ReportParameter[9];
                repParams[0] = new ReportParameter("StationNo", Session["StationNo"].ToString());
                repParams[1] = new ReportParameter("StationName", Session["StationName"].ToString());
                repParams[2] = new ReportParameter("DateTo", Session["DateTo"].ToString());
                repParams[3] = new ReportParameter("DateFrom", Session["DateFrom"].ToString());
                repParams[4] = new ReportParameter("OpenedBy", Session["OpenedBy"].ToString());
                repParams[5] = new ReportParameter("AssignedOperator", Session["AssignedOperator"].ToString());
                repParams[6] = new ReportParameter("Status", Session["Status"].ToString());
                repParams[7] = new ReportParameter("ReceiptNumber", Session["ReceiptNumber"].ToString());
                repParams[8] = new ReportParameter("BusinessUnit", Session["BusinessUnit"].ToString());
                this.JobCardsReport_ReportViewer.LocalReport.SetParameters(repParams);

                dt_JobCardsDataTable dt = new dt_JobCardsDataTable();
                dt.Adddt_JobCardsRow("2024-01-02");
                ReportDataSource rds = new ReportDataSource("JobCards", (DataTable)dt);
                JobCardsReport_ReportViewer.LocalReport.DataSources.Add(rds);
            }

the ASPX view page file:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="JobCardsReport.aspx.cs" Inherits="APCReports.ReportsView.JobCardsReport" %>
<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=15.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>Job Cards Report</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
            
            <!-- ReportViewer control -->
            <rsweb:ReportViewer ID="JobCardsReport_ReportViewer" runat="server" AsyncRendering="False" Width="100%" Height="500px">
                <LocalReport ReportPath="ReportViews/JobCardsReport.rdlc">
               </LocalReport>
            </rsweb:ReportViewer>
        </div>
    </form>
</body>
</html>

I had a similar report working before, but after comparing them i could not find any difference, and I was following the exact same steps. i can't see what wrong here

NOTE: for simplicity's sake, the the DataTable has one string column only, and its fed with simple static data


Solution

  • After much more testing, it looks like Page_Load does not quite work asynchronously (namely, the keyword async), which will force using synchronous code all the way.

    Since then, I have switched to a .NET 6 MVC project, and Im using the package AspNetCore.Reporting for rendering reports on a pdf viewer without the need of ASPX pages.