}//jError()

        public static void error(CswNbtResources CswNbtResources, Exception ex, out CswEnumErrorType Type, out string Message, out string Detail, out bool Display)
        {
            if (CswNbtResources != null)
            {
                CswNbtResources.CswLogger.reportError(ex);
                CswNbtResources.Rollback();
            }

            CswDniException newEx = null;

            if (ex is CswDniException)
            {
                newEx = (CswDniException)ex;
            }
            else
            {
                newEx = new CswDniException(ex.Message, ex);
            }

            Display = true;
            Type    = newEx.Type;
            Message = newEx.MsgFriendly;
            Detail  = newEx.MsgEscoteric + "; ";

            if (CswNbtResources != null)
            {
                if (newEx.Type == CswEnumErrorType.Warning)
                {
                    Display = (CswNbtResources.ConfigVbls.getConfigVariableValue("displaywarningsinui") != "0");
                }
                else
                {
                    Display = (CswNbtResources.ConfigVbls.getConfigVariableValue("displayerrorsinui") != "0");
                }

                if (CswNbtResources.ShowFullStackTraceInUI)
                {
                    Detail += ex.StackTrace;
                }
            }
        } // _error()
        private static DataTable _getReportTable( ICswResources CswResources, CswNbtWebServiceReport.ReportData reportParams )
        {
            CswNbtResources NbtResources = (CswNbtResources) CswResources;
            DataTable rptDataTbl = null;
            reportParams.ReportNode = NbtResources.Nodes[reportParams.NodeId];
            if( null != reportParams.ReportNode )
            {
                if( false == string.IsNullOrEmpty( reportParams.ReportNode.WebService.Text ) )
                {

                    // See cases: 28562, 31102, 31147, 31190
                    // All of my efforts to get this report to execute using self-referencing webservices have failed.
                    // If I use 'localhost', I get SSL errors with https://.
                    // If I use a real URL, like 'https://nbtdaily.chemswlive.com/CiTest/', then I simply get empty strings back.
                    // So I'm going to use reflection to find and execute the method instead.


                    ////// case 31102
                    ////// Determine the webservice URL from the request URL
                    ////// Use 'localhost' however, since daily/prod may not be able to see its own DNS
                    //////string thisUrl = reportParams.Context.Request.Url.AbsoluteUri;
                    ////string thisUrl = reportParams.Context.Request.Url.Scheme + "://localhost" + reportParams.Context.Request.Url.LocalPath;
                    ////string thisUrlBase = thisUrl.Substring( 0, thisUrl.IndexOf( "/Services/" ) + "/Services/".Length );
                    ////string WebServiceUrl = thisUrlBase + CswNbtObjClassReport.ReplaceReportParams( reportParams.ReportNode.WebService.Text, reportParams.ReportParamDictionary );
                    //string WebServiceUrl = NbtResources.SetupVbls[CswEnumSetupVariableNames.MailReportUrlStem] + "Services/" + CswNbtObjClassReport.ReplaceReportParams( reportParams.ReportNode.WebService.Text, reportParams.ReportParamDictionary );

                    //HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create( WebServiceUrl );
                    //request.Method = "GET";
                    //request.CookieContainer = new CookieContainer();
                    //foreach( string c in reportParams.Context.Request.Cookies.Keys )
                    //{
                    //    HttpCookie cookie = reportParams.Context.Request.Cookies[c];
                    //    if( cookie.Name == "CswSessionId" )
                    //    {
                    //        request.CookieContainer.Add( new Cookie()
                    //            {
                    //                Name = cookie.Name,
                    //                Value = cookie.Value,
                    //                Domain = "localhost",
                    //                Path = cookie.Path
                    //            } );
                    //    }
                    //}
                    //HttpWebResponse response = (HttpWebResponse) request.GetResponse();
                    //rptDataTbl = new DataTable();

                    //StreamReader sr = new StreamReader( response.GetResponseStream() );
                    //string result = sr.ReadToEnd();
                    //result = result.Replace( @"\", "" );
                    //if( result.StartsWith( "\"" ) )
                    //{
                    //    result = result.Substring( 1, result.Length - 2 );
                    //}
                    ////result = @"<?xml version=""1.0"" encoding=""utf-8""?>" + result;
                    ////rptDataTbl.ReadXml( response.GetResponseStream() );
                    //if( false == string.IsNullOrEmpty( result ) )
                    //{
                    //    rptDataTbl.ReadXml( new StringReader( result ) );
                    //}


                    // reportParams.ReportNode.WebService.Text is something like "RegulatoryReporting/getHMISDataTable?ControlZone={Name}"
                    string[] WebServiceStr = reportParams.ReportNode.WebService.Text.Split( '/' );
                    string wsClassName = "NbtWebApp." + WebServiceStr[0];
                    string[] rawParams = WebServiceStr[WebServiceStr.Length - 1].Split( new char[] { '?', '&' } );
                    string wsMethodName = rawParams[0];
                    object[] wsParams = new object[rawParams.Length - 1];
                    for( Int32 w = 1; w < rawParams.Length; w++ )
                    {
                        string[] thisParam = rawParams[w].Split( '=' );
                        string paramValue = CswNbtObjClassReport.ReplaceReportParams( thisParam[1], reportParams.ReportParamDictionary );
                        wsParams[w - 1] = paramValue;
                    }

                    Type classInfo = Type.GetType( wsClassName );
                    if( null != classInfo )
                    {
                        var classInstance = classInfo.GetConstructor( System.Type.EmptyTypes ).Invoke( null );
                        MethodInfo methodInfo = classInfo.GetMethod( wsMethodName );
                        if( null != methodInfo )
                        {
                            rptDataTbl = (DataTable) methodInfo.Invoke( classInstance, wsParams );
                        }
                    }
                }
                else if( false == string.IsNullOrEmpty( reportParams.ReportNode.SQL.Text ) )
                {
                    string ReportSql = "";
                    //Case 30293: We are not trying to solve all of the (usability) issues with SQL Reporting today;
                    //rather, we just want to return friendlier errors when SQL faults occur
                    try
                    {
                        ReportSql = CswNbtObjClassReport.ReplaceReportParams( reportParams.ReportNode.SQL.Text, reportParams.ReportParamDictionary );
                        CswArbitrarySelect cswRptSql = NbtResources.makeCswArbitrarySelect( "report_sql", ReportSql );

                        reportParams.RowLimit = CswConvert.ToInt32( NbtResources.ConfigVbls.getConfigVariableValue( CswEnumNbtConfigurationVariables.sql_report_resultlimit.ToString() ) );
                        if( 0 >= reportParams.RowCount )
                        {
                            reportParams.RowCount = 500;
                        }

                        //Getting 1 more than RowLimit in order to determine if truncation occurred
                        rptDataTbl = cswRptSql.getTable( PageLowerBoundExclusive: 0, PageUpperBoundInclusive: reportParams.RowLimit + 1, RequireOneRow: false );
                        if( string.IsNullOrEmpty( rptDataTbl.TableName ) && null != reportParams.ReportNode )
                        {
                            rptDataTbl.TableName = reportParams.ReportNode.ReportName.Text;
                        }
                    }
                    catch( CswSqlException CswException )
                    {
                        CswDniException NewException = new CswDniException( CswEnumErrorType.Warning, "SQL Execution failed with error: " + CswException.OracleError, "Could not execute SQL: {" + CswException.Sql + "}", CswException );
                        //CswException.Add( NewException );
                        throw NewException;
                    }
                    catch( Exception Ex )
                    {
                        throw new CswDniException( CswEnumErrorType.Warning, "Invalid SQL.", "Could not execute SQL: {" + ReportSql + "}", Ex );
                    }
                    finally
                    {
                        if( null != rptDataTbl )
                        {
                            reportParams.RowCount = rptDataTbl.Rows.Count;
                            reportParams.Truncated = reportParams.RowCount > reportParams.RowLimit;
                            if( reportParams.Truncated )
                            {
                                rptDataTbl.Rows.RemoveAt( reportParams.RowCount - 1 );
                                reportParams.RowCount -= 1;
                            }
                        }
                    }
                }
                else
                {
                    throw ( new CswDniException( "Report has no SQL to run!" ) );
                }
            }
            return rptDataTbl;
        }