Skip to main content Skip to footer

How to Solve Custom Errors in Your ASP.NET Reporting Application

The quality of a website is not only judged by how well the website works but how gracefully it fails. When there is an error with ActiveReports it displays the error (a stack trace) in the web viewer in an alert box style box but leaves you as the developer limited in how you can handle the error or log the error. It is important to point out that an "Error" needs to be handled differently. We need to let the user know there is a problem, but we don't want to inform them via a stack dump. It is vice versa for the developers, they don't care that an error happened per se, but they are interested in what caused the error.

Luckily, we can completely customize the way we handle application errors in ActiveReports. Let's think of a scenario where you have a large website that integrates ActiveReports into it. Let's say our ActiveReports connects to a server to get its data.

We, as developers, cannot be promised that the connection to our Database will always be valid for many reasons outside our control. If our website loses connection to its database server, we don't want our users to suffer from it by simply giving them a stack dump or a server error. We want to provide our users with ways to get assistance in resolving the issue. Also, we don't want our users to know that there is an issue with the DB connection; we simply want to tell them that there is an issue, and they can contact customer support to report the issue and resolve it.

This sample demonstrates how we can deal with these issues and show you how to handle errors with ActiveReports in a web environment. If there is an issue with ActiveReports, it will simply redirect the user to a custom error page. We can display IT contact information and email the Errors to your support team or IT team without the user knowing. First, we need to tell our website that we want to handle errors in a custom manner. This can be accomplished by setting the web.config file properly. In our System.Web tag in our Web.config, we need to add the following entry:

 <customErrors mode="On" defaultRedirect="~/Oops.aspx" redirectMode="ResponseRewrite">  
 </customErrors>  

also, you may need the following settings:

  <appSettings>
    <add key="owin:AutomaticAppStartup" value="false" />
    <add key="owin:appStartup" value="MyNameSpace.Global" />
  </appSettings>

The section enables configuration of what to do if/when an unhandled error occurs during the execution of a request. Specifically, it enables developers to configure HTML error pages to be displayed in place of an error stack trace. Once we told our website that we want to handle errors ourselves, we need to create a folder on the website called CustomErrors and create a webform called Oops.aspx.

The Oops.aspx page will display the tech support information in the scenario. We can add some generic text to the webform such as "Hello from Opps Page". Now that we have CustomError handling enabled and the link to the customer error page is setup, let's move back to our Default.aspx page that holds the viewer for our ActiveReports Report.

To set up the WebViewer middleware, we need to update Global.asax.cs with the following code:

protected void Application_Start(object sender, EventArgs e)
        {

            this.UseReporting(settings =>
            {
                settings.UseCompression = true;
            });
        }

Let’s go to the VB or CS code-behind for our Default.aspx page ( Default.aspx.cs ). In a basic Report viewing webpage, it would look like this:

        protected void Page_Load(object sender, EventArgs e)
        {
                var rpt = new MyReport();
                arWebViewer.Report = rpt;
        }  

In this case, we create a new Object in our Report, Run the Report, and Bind it to the viewer. To handle any errors caused by this, we need to add some Try, Catch statements around that code. See below:

protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                var rpt = new MyReport();
                //test
                //rpt.ReportStart += Rpt_ReportStart;

                try
                {
                    rpt.Run();
                    arWebViewer.Report = rpt;
                }
                catch (GrapeCity.ActiveReports.ReportException ex)
                {
                    throw new GrapeCity.ActiveReports.ReportException(ex.Message);
                }                
            }
        }

        private void Rpt_ReportStart(object sender, EventArgs e)
        {
            throw new GrapeCity.ActiveReports.ReportException();
        }

For JSViewer, you would need to use the custom storage, and the code may look like this:

        protected void Application_Start(object sender, EventArgs e)
        {
            this.UseReporting(settings =>
            {
                settings.UseCompression = true;
                settings.UseCustomStore(GetReport);
            });
           
        }
        protected object GetReport(string name)
        {
            var rpt = new MyReport();
            try
            {
                rpt.Run();
            }
            catch (GrapeCity.ActiveReports.ReportException ex)
            {
                throw new GrapeCity.ActiveReports.ReportException(ex.Message);
            }
            return rpt;
        }

This way, any errors that are thrown by ActiveReports will be caught in _ex_ as an exception and logged on the server. If an error is detected, the website will look into the web.config and redirect the user to the customError handler re-direct. We can stop here if we only want to abstract the error away from the user. If we're going to catch the error and display it on the new page or write the error to a file on disk or email an error report out, we need to add some code to the Oops.aspx.cs file ( the code behind the Oops.aspx page.)

protected void Page_Load(object sender, EventArgs e)  
    {  
       string js = "" + (String)GetValue()+";";  
       ClientScript.RegisterStartupScript(Page.GetType(), "UniqueKeyForThisScript", js, false);  
    }  
   private string GetValue()  
    {  
         Exception ex = Server.GetLastError();  
       if ( ex != null )  
        {  
            if( ex.GetBaseException() != null)  
          {  
           ex = ex.GetBaseException();  
             }  
        }  
        return ex.ToString();  
     }  

So basically, what is going on here is that we grab the LastError off the server and check to make sure it's not null. We return the string back to the Page_Load. This is where you can customize what you do with the error as a developer. In the code above, we’ve inserted the string into the page for debugging purposes; you can replace that code with a File.IO write or an email send function. 

Download the sample.

Tags:

comments powered by Disqus