Hangfire + Crystal Reports email?

550 views Asked by At

I'm trying to make it so that we can generate certain reports daily and email them to a bunch of people in a list.

I've tested out Hangfire for recurring jobs and it works well. So that is not an issue. But I'm trying to create a report from my existing Crystal Report file (.rpt). Basically I want to make it so that when this job gets executed, the code would create the report, save it to the disk in a specified path as a PDF, and then I can email it to people as an attachment. So there is no need to be able to see the report on a web page. The idea is to literally just generate the report in the code behind, save it as a PDF, and email it from the code behind after it is saved.

The issue I'm having has to do with the actual generating and saving of the crystal report. Btw, I'm generating an excel file in the test but I'd change it to PDF for the actual report. This is what I have so far for generating the report:

        string path = @"Save folder relative-path";
        //"report" is declared at the class level and instantiated below.
        report = new ReportDocument();
        report.SetDatabaseLogon(ConfigurationManager.AppSettings["Username"], ConfigurationManager.AppSettings["Password"]);
        report.Load(Server.MapPath("Relative path to the report"));
        report.SetDataSource(GetDataSet()); //This gets the dataset filled with data for the report

        try
        {
            ExportOptions options = new ExportOptions();

            DiskFileDestinationOptions diskFileOptions = new DiskFileDestinationOptions();
            ExcelFormatOptions excelOptions = new ExcelFormatOptions();
            diskFileOptions.DiskFileName = path + "Test Report.xls";

            options.ExportDestinationType = ExportDestinationType.DiskFile;
            options.ExportFormatType = ExportFormatType.Excel;
            options.ExportDestinationOptions = diskFileOptions;
            options.ExportFormatOptions = excelOptions;
            report.Export();

            /*
            This is where I would call a method to email the report to people
            */
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error generating report: " + ex.Message);
        }

This code is in a method which is being called at Application_Start in the global.asax file of the web application. When I run the application, the job fails and throws this error when I look under the failed jobs in the Hangfire dashboard even though I know the path in my code is correct:

System.IO.FileNotFoundException Could not load file or assembly 'App_global.asax.twm32qri, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

System.IO.FileNotFoundException: Could not load file or assembly 'App_global.asax.twm32qri, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. File name: 'App_global.asax.twm32qri, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type) at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName) at System.Type.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase) at Hangfire.Storage.InvocationData.Deserialize()

WRN: Assembly binding logging is turned OFF. To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1. Note: There is some performance penalty associated with assembly bind failure logging. To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].

EDIT:

I have another error I'm getting too. This one has something to do with loading the report file.

Failed An exception occurred during performance of the job. CrystalDecisions.CrystalReports.Engine.LoadSaveReportException

Invalid report file path.

CrystalDecisions.CrystalReports.Engine.LoadSaveReportException: Invalid report file path. at CrystalDecisions.CrystalReports.Engine.ExceptionThrower.ThrowEngineException(String messageID, EngineExceptionErrorID id) at CrystalDecisions.CrystalReports.Engine.ReportDocument.Load(String filename, OpenReportMethod openMethod, Int16 parentJob) at CrystalDecisions.CrystalReports.Engine.ReportDocument.EnsureLoadReport() at CrystalDecisions.CrystalReports.Engine.ReportDocument.SetDatabaseLogon(String user, String password) at Intranet.Global.GenerateReport() in path\Global.asax.cs:line 98

1

There are 1 answers

0
David Flynn On BEST ANSWER

Figured out the issue. I apparently needed to use a CrystalReportViewer object and set the ReportDocument object as its source. The CrystalReportViewer class is in the CrystalDecisions.Web namespace.

using (ReportDocument report = new ReportDocument())
{
    using (CrystalReportViewer viewer = new CrystalReportViewer())
    {
        string path = System.Web.Hosting.HostingEnvironment.MapPath(@"Destination path here");
        report.Load(System.Web.Hosting.HostingEnvironment.MapPath(@"Path to .rpt file here"));
        report.SetDatabaseLogon(ConfigurationManager.AppSettings["Username"], ConfigurationManager.AppSettings["Password"]);

        string file = path + "TestReport.xls";

        //These two lines below are important. The report won't generate without them.
        viewer.ReportSource = report;
        viewer.RefreshReport();

        //Just deleting the file if it exists.
        if (File.Exists(file))
            File.Delete(file);

        report.ExportToDisk(ExportFormatType.Excel, diskFileOptions.DiskFileName);
    }
}