Search code examples
c#asp.netcrystal-reports

Crystal Reports only works when 'Save data in the report' is checked


I am using Crystal Reports Version 13.0.2000.0 in a C# ASP.Net web application that connects to a SQL Server. When loading a report, I am only able to view the table contents if I have checked 'Save data in the report'.

This is great when I don't expect my data to change. However, if - for example - A user were to change their status from Active to Inactive, and I wanted to display all Active users in my report. The user would still appear in my Active Users report.

I have unchecked 'Save data in the report', and the changes to my report are validated when I check the report preview. However, when I try to view the report on the website, I am asked to provide login information 'The report you requested requires further information.' which when entered, does nothing but send me back to enter the login information again.

I understand that when 'Save data in the report is checked' that the report doesn't actually query the database, it just uses the saved data, and when it is unchecked it requests the data from the server, but I don't understand why it isn't using the login information that I have provided.

Here is how I view my reports:

protected void Page_Load(object sender, EventArgs e)
{

    //string reportPath = Server.MapPath(ConfigurationManager.AppSettings["reportspath"].ToString());
    string reportPath = Server.MapPath("../DynamicReports/");
    string rpName = (string)Utils.GetSessionNavigator(this).GetDataFromCurrentPage(PageParams.Reports.Report);

    ReportDocument rep = new ReportDocument();

    try
    {
        rep.Load(reportPath + rpName);
        LoadReport(rep);

        this.CrystalReportViewer1.ToolPanelView = CrystalDecisions.Web.ToolPanelViewType.None;
        this.CrystalReportViewer1.HasToggleGroupTreeButton = false;
        this.CrystalReportViewer1.ReportSource = rep;

    }
    catch (Exception ex)
    {
        Response.Write(ex.Message);
    }
}

private bool LoadReport(ReportDocument doc)
{
    TableLogOnInfo crTableLogonInfo;
    Sections crSections;
    Database crDatabase;
    Tables crTables;
    ReportDocument crSubreportDocument;
    ReportObjects crReportObjects;
    SubreportObject crSubreportObject;

    try
    {
        ConnectionInfo con = new ConnectionInfo();
        con.ServerName = "******";
        con.DatabaseName = Utils.GetSessionNavigator(this).UserData.DatabaseName;
        con.UserID = "******";
        con.Password = "******";
        con.Type = ConnectionInfoType.SQL;
        con.IntegratedSecurity = false;

        crDatabase = doc.Database;
        crTables = crDatabase.Tables;

        //loop through all the tables and pass in the connection info
        foreach (CrystalDecisions.CrystalReports.Engine.Table crTable in crTables)
        {
            crTableLogonInfo = crTable.LogOnInfo;
            crTableLogonInfo.ConnectionInfo = con;
            crTable.ApplyLogOnInfo(crTableLogonInfo);
        }

        // set the crSections object to the current report's sections
        crSections = doc.ReportDefinition.Sections;

        // loop through all the sections to find all the report objects
        foreach (Section crSection in crSections)
        {
            crReportObjects = crSection.ReportObjects;
            // loop through all the report objects to find all the subreports
            foreach (ReportObject crReportObject in crReportObjects)
            {
                if (crReportObject.Kind == ReportObjectKind.SubreportObject)
                {
                    crSubreportObject = (SubreportObject)crReportObject;

                    // open the subreport object
                    crSubreportDocument = crSubreportObject.OpenSubreport(crSubreportObject.SubreportName);

                    // set the database and tables objects to work with the subreport
                    crDatabase = crSubreportDocument.Database;
                    crTables = crDatabase.Tables;

                    // loop through all the tables in the subreport and 
                    // set up the connection info and apply it to the tables
                    foreach (CrystalDecisions.CrystalReports.Engine.Table crTable in crTables)
                    {
                        crTableLogonInfo = crTable.LogOnInfo;
                        crTableLogonInfo.ConnectionInfo = con;
                        crTable.ApplyLogOnInfo(crTableLogonInfo);
                    }
                }
            }
        }
    }
    catch (Exception e)
    {
        Response.Write(e.Message);
        return false;
    }
    return true;
}

I have been debugging my code and everything seems to check out fine, but as I am inexperienced with Crystal reports I have the feeling I am missing something obvious.

Thanks for any suggestions SO!

Edit 1: I have changed:

    foreach (CrystalDecisions.CrystalReports.Engine.Table crTable in crTables)
    {
        crTableLogonInfo = crTable.LogOnInfo;
        crTableLogonInfo.ConnectionInfo = con;
        crTable.ApplyLogOnInfo(crTableLogonInfo);
    }

to:

foreach (CrystalDecisions.CrystalReports.Engine.Table crTable in crTables)
            {
                crTable.LogOnInfo.ConnectionInfo = con;
            }

which now allows me to log in to view the contents of the report. However, I still want to get rid of the log in screen entirely, but I don't know how to proceed.


Solution

  • Some time has passed since I figured out the solution to this problem, but I'll leave the answer here for others, after calling the LoadReport() method, all I needed to do was add:

    rep.SetDatabaseLogon("******", "******");