Exemplo n.º 1
0
        static void Main(string[] args)
        {
            //parse params from command line
            var parameterValues =
                (from a in args
                 where a.StartsWith("/p:")
                 let parts = a.Substring(3).Split('=')
                             select new ParameterValue
            {
                Name = parts[0],
                Value = parts[1]
            })
                .ToArray();

            bool hideDetail = parameterValues
                              .Where(pv => pv.Name == "HideDetail")
                              .Select(pv => (bool.TrueString.Equals(pv.Value ?? "false", StringComparison.OrdinalIgnoreCase)))
                              .DefaultIfEmpty(false)
                              .FirstOrDefault();

            //Load report options. In production this will come from the DB, but for this test app, load from Options.xml file
            XElement optionsElement       = XElement.Load("Options.xml");
            string   reportPath           = (string)optionsElement.Element("ReportPath");
            XElement reportColumnsElement = optionsElement.Element("ReportColumns");

            //get rdl template from server
            var reportService = new Emdat.InVision.SSRS.ReportingService2005();

            reportService.UseDefaultCredentials = true;
            byte[] rdlTemplate = reportService.GetReportDefinition(reportPath);

            using (var rdlTemplateStream = new MemoryStream(rdlTemplate))
            {
                string format = "CSV";

                //load RDL into XElement
                XElement rdlTemplateElement = XElement.Load(rdlTemplateStream);

                //generate the RDL
                byte[] reportDefinition = ReportGenerator.GenerateReportDefinition(rdlTemplateElement, reportColumnsElement, hideDetail, format);

                //output the rdl file for debugging
                File.WriteAllBytes("reportDefinition.rdl", reportDefinition);

                //execute the report using the new RDL
                var reportExecution = new Emdat.InVision.SSRSExecution.ReportExecutionService();
                reportExecution.UseDefaultCredentials = true;

                Emdat.InVision.SSRSExecution.Warning[] warnings;
                string   extension;
                string   mimeType;
                string   encoding;
                string[] streamIds;

                var executionInfo = reportExecution.LoadReportDefinition(reportDefinition, out warnings);
                reportExecution.ExecutionHeaderValue = new Emdat.InVision.SSRSExecution.ExecutionHeader()
                {
                    ExecutionID = executionInfo.ExecutionID
                };

                //set report parameter values
                executionInfo = reportExecution.SetExecutionParameters(parameterValues, "en-us");

                byte[] pdf;
                string deviceInfo = "<DeviceInfo><MarginLeft>0.5in</MarginLeft></DeviceInfo>";
                //pdf = reportExecution.Render(format, deviceInfo, out extension, out mimeType, out encoding, out warnings, out streamIds);

                //render to PDF
                var    requestBuilder = new StringBuilder();
                string xmlnsSoap      = "http://schemas.xmlsoap.org/soap/envelope/";
                string xmlnsSSRS      = "http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices";
                using (var xw = XmlWriter.Create(requestBuilder))
                {
                    xw.WriteStartElement("Envelope", xmlnsSoap);
                    xw.WriteStartElement("Header", xmlnsSoap);
                    xw.WriteStartElement("ExecutionHeader", xmlnsSSRS);
                    xw.WriteElementString("ExecutionID", xmlnsSSRS, executionInfo.ExecutionID);
                    xw.WriteEndElement();
                    xw.WriteEndElement();
                    xw.WriteStartElement("Body", xmlnsSoap);
                    xw.WriteStartElement("Render", xmlnsSSRS);
                    xw.WriteElementString("Format", xmlnsSSRS, format);
                    xw.WriteElementString("DeviceInfo", xmlnsSSRS, deviceInfo);
                    xw.WriteEndElement();
                    xw.WriteEndElement();
                    xw.WriteEndElement();
                }

                var requestBytes = Encoding.UTF8.GetBytes(requestBuilder.ToString());

                var renderRequest = (HttpWebRequest)WebRequest.Create(reportExecution.Url);
                renderRequest.Method = "POST";
                renderRequest.UseDefaultCredentials = true;
                renderRequest.Headers.Add("SOAPAction", "http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices/Render");
                renderRequest.ContentType   = "text/xml; charset=utf-8";
                renderRequest.ContentLength = requestBytes.LongLength;
                using (var requestStream = renderRequest.GetRequestStream())
                {
                    requestStream.Write(requestBytes, 0, requestBytes.Length);
                }
                try
                {
                    using (var response = renderRequest.GetResponse())
                    {
                        //TODO: check error code and content type, etc.

                        using (var responseStream = response.GetResponseStream())
                        {
                            XNamespace soap           = xmlnsSoap;
                            XNamespace ssrs           = xmlnsSSRS;
                            XElement   soapEnvelope   = XElement.Load(responseStream);
                            var        renderResponse = soapEnvelope.Elements(soap + "Body").Elements(ssrs + "RenderResponse").First();

                            string base64Result = (string)renderResponse.Element(ssrs + "Result");
                            pdf = Convert.FromBase64String(base64Result);

                            extension = (string)renderResponse.Element(ssrs + "Extension");
                            mimeType  = (string)renderResponse.Element(ssrs + "MimeType");
                            warnings  =
                                (from w in renderResponse.Elements(ssrs + "Warnings").Elements(ssrs + "Warning")
                                 select new Warning
                            {
                                Code = (string)w.Element("Code"),
                                Severity = (string)w.Element("Severity"),
                                Message = (string)w.Element("Message"),
                                ObjectName = (string)w.Element("ObjectName"),
                                ObjectType = (string)w.Element("ObjectType")
                            })
                                .ToArray();
                        }
                    }

                    //save to file and open
                    File.WriteAllBytes("output." + "csv", pdf);
                    System.Diagnostics.Process.Start("output." + "csv");
                }
                catch (WebException ex)
                {
                    if (ex.Response == null)
                    {
                        throw;
                    }
                    using (var responseStream = ex.Response.GetResponseStream())
                        using (var fs = File.Create("WebException.txt"))
                        {
                            responseStream.CopyTo(fs);
                        }
                    throw;
                }
            }
        }
Exemplo n.º 2
0
        public void ExecuteAsync(ICredentials reportServerCredentials, TimeSpan timeout, string format)
        {
            #region logging

            Log(TraceEventType.Verbose, "BEGIN ExecuteAsync()");

            #endregion

            try
            {
                if (this.State != ReportExecutionStateEnum.Queued)
                {
                    throw new InvalidOperationException(string.Format("Execution {0} cannot be run from its current state: {1}", this.Id, this.State));
                }

                try
                {
                    _cancelExecution = false;
                    this.State       = ReportExecutionStateEnum.Running;
                    this.StartTime   = DateTime.Now;

                    //create a reference to the web service
                    using (Emdat.InVision.SSRSExecution.ReportExecutionService rs = new Emdat.InVision.SSRSExecution.ReportExecutionService())
                    {
                        //configure the web service
                        if (reportServerCredentials != null)
                        {
                            rs.UseDefaultCredentials = false;
                            rs.Credentials           = reportServerCredentials;
                        }
                        else
                        {
                            rs.UseDefaultCredentials = true;
                        }
                        rs.Timeout = (int)timeout.TotalMilliseconds;

                        string historyId = null;

                        #region logging

                        Log(TraceEventType.Information, "LoadReport(reportPath='{0}', historyId='{1}')", this.ReportPath, historyId);

                        #endregion

                        //load the report
                        Emdat.InVision.SSRSExecution.ExecutionInfo execInfo = null;

                        XElement customColumns = GetCustomColumns();
                        if (null != customColumns && null != customColumns.Element("Columns") && 0 < customColumns.Element("Columns").DescendantNodes().Count())
                        {
                            var hideDetail = false;
                            //var reportFormat = "xml";

                            foreach (var parameter in this.Parameters)
                            {
                                if ("HideDetail" == parameter.Name)
                                {
                                    Boolean.TryParse(parameter.Value, out hideDetail);
                                    break;
                                }
                            }

                            using (var reportingService = new Emdat.InVision.SSRS.ReportingService2005())
                            {
                                reportingService.UseDefaultCredentials = rs.UseDefaultCredentials;
                                reportingService.Credentials           = rs.Credentials;

                                byte[] rdlTemplate = reportingService.GetReportDefinition(this.ReportPath);

                                using (var rdlTemplateStream = new MemoryStream(rdlTemplate))
                                    using (var rdlTemplateReader = XmlReader.Create(rdlTemplateStream))
                                    {
                                        XElement rdlTemplateElement = XElement.Load(rdlTemplateReader);
                                        byte[]   generatedRdl       = ReportGenerator.GenerateReportDefinition(rdlTemplateElement, customColumns, hideDetail, format);

                                        Emdat.InVision.SSRSExecution.Warning[] warnings = null;
                                        execInfo = rs.LoadReportDefinition(generatedRdl, out warnings);
                                    }
                            }
                        }
                        else
                        {
                            execInfo = rs.LoadReport(this.ReportPath, historyId);
                        }

                        rs.ExecutionHeaderValue = new Emdat.InVision.SSRSExecution.ExecutionHeader()
                        {
                            ExecutionID = execInfo.ExecutionID
                        };

                        #region logging

                        var prmStr = from p in this.Parameters select string.Format("{0}:{1}", p.Name, p.Value);

                        Log(TraceEventType.Information, "SetExecutionParameters(prms='{0}', prmLanguage='{1}')", string.Join(";", prmStr.ToArray()), this.ParameterLanguage);

                        #endregion

                        try
                        {
                            //set the parameters
                            execInfo = rs.SetExecutionParameters(this.Parameters.ToArray(), this.ParameterLanguage);
                        }
                        catch (Exception ex)
                        {
                            Log(TraceEventType.Information, "{0}", ex);
                            throw new ReportExecutionException(ReportExecutionErrorEnum.InvalidReportParameter, ex.Message);
                        }
                        //validate parameters (just make sure they all have valid values)
                        foreach (var p in execInfo.Parameters)
                        {
                            if (p.State != Emdat.InVision.SSRSExecution.ParameterStateEnum.HasValidValue)
                            {
                                throw new ReportExecutionException(
                                          ReportExecutionErrorEnum.InvalidReportParameter,
                                          string.Format(string.Format("Invalid parameter value specified for {0}: {1}. {2}",
                                                                      p.Name,
                                                                      string.Join(";", (from pv in this.Parameters where pv.Name == p.Name select pv.Value).ToArray()),
                                                                      p.ErrorMessage)));
                            }
                        }

                        //We are using URL access to the report server so that we
                        //can support streaming and have a little more control over
                        //the whole rendering process.
                        //string deviceInfoQueryString = GetDeviceInfoQueryString();
                        //string url = string.Format(
                        //    @"{0}?{1}&rs:SessionId={2}&rs:Format={3}{4}{5}",
                        //    rs.Url.Replace("ReportExecution2005.asmx", string.Empty),
                        //    execInfo.ReportPath,
                        //    execInfo.ExecutionID,
                        //    this.Format,
                        //    !string.IsNullOrEmpty(deviceInfoQueryString) ? "&" : string.Empty,
                        //    deviceInfoQueryString);

                        //render to PDF
                        var    requestBuilder = new StringBuilder();
                        string xmlnsSoap      = "http://schemas.xmlsoap.org/soap/envelope/";
                        string xmlnsSSRS      = "http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices";
                        using (var xw = XmlWriter.Create(requestBuilder))
                        {
                            xw.WriteStartElement("Envelope", xmlnsSoap);
                            xw.WriteStartElement("Header", xmlnsSoap);
                            xw.WriteStartElement("ExecutionHeader", xmlnsSSRS);
                            xw.WriteElementString("ExecutionID", xmlnsSSRS, execInfo.ExecutionID);
                            xw.WriteEndElement();
                            xw.WriteEndElement();
                            xw.WriteStartElement("Body", xmlnsSoap);
                            xw.WriteStartElement("Render", xmlnsSSRS);
                            xw.WriteElementString("Format", xmlnsSSRS, this.Format);
                            xw.WriteElementString("DeviceInfo", xmlnsSSRS, this.DeviceInfo);
                            xw.WriteEndElement();
                            xw.WriteEndElement();
                            xw.WriteEndElement();
                        }

                        var requestBytes = Encoding.UTF8.GetBytes(requestBuilder.ToString());

                        _renderRequest = WebRequest.Create(rs.Url);
                        _renderRequest.UseDefaultCredentials = rs.UseDefaultCredentials;
                        _renderRequest.Credentials           = rs.Credentials;
                        _renderRequest.Timeout = rs.Timeout;
                        _renderRequest.Method  = "POST";
                        _renderRequest.Headers.Add("SOAPAction", "http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices/Render");
                        _renderRequest.ContentType   = "text/xml; charset=utf-8";
                        _renderRequest.ContentLength = requestBytes.LongLength;
                        using (var requestStream = _renderRequest.GetRequestStream())
                        {
                            requestStream.Write(requestBytes, 0, requestBytes.Length);
                        }

                        #region logging

                        Log(TraceEventType.Verbose, "BEGIN GetResponse(url={0})", rs.Url);

                        #endregion

                        _renderRequest.BeginGetResponse(
                            delegate(IAsyncResult ar)
                        {
                            try
                            {
                                try
                                {
                                    #region logging

                                    Log(TraceEventType.Verbose, "END GetResponse(url={0})", rs.Url);

                                    #endregion

                                    if (_cancelExecution)
                                    {
                                        return;
                                    }

                                    //end the asynchronous call
                                    using (WebResponse response = _renderRequest.EndGetResponse(ar))
                                    {
                                        //raise RenderCompleted event
                                        OnRenderCompleted();

                                        try
                                        {
                                            #region logging

                                            Log(TraceEventType.Verbose, "END GetResponse(url={0})", rs.Url);

                                            #endregion

                                            //download data to a temporary file
                                            string tempFile = this.GetTempFilePath();
                                            try
                                            {
                                                Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
                                                using (Stream readStream = response.GetResponseStream())
                                                    using (XmlReader xmlReader = XmlReader.Create(readStream))
                                                    {
                                                        XNamespace soap = "http://schemas.xmlsoap.org/soap/envelope/";
                                                        XNamespace ssrs = "http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices";

                                                        XElement soapEnvelope = XElement.Load(xmlReader);
                                                        var renderResponse    = soapEnvelope.Elements(soap + "Body").Elements(ssrs + "RenderResponse").First();

                                                        string base64Result = (string)renderResponse.Element(ssrs + "Result");
                                                        byte[] pdf;
                                                        pdf = Convert.FromBase64String(base64Result);

                                                        String extension   = (string)renderResponse.Element(ssrs + "Extension");
                                                        String mimeType    = (string)renderResponse.Element(ssrs + "MimeType");
                                                        Warning[] warnings =
                                                            (from w in renderResponse.Elements(ssrs + "Warnings").Elements(ssrs + "Warning")
                                                             select new Warning
                                                        {
                                                            Code = (string)w.Element("Code"),
                                                            Severity = (string)w.Element("Severity"),
                                                            Message = (string)w.Element("Message"),
                                                            ObjectName = (string)w.Element("ObjectName"),
                                                            ObjectType = (string)w.Element("ObjectType")
                                                        }).ToArray();
                                                        this.Data = pdf;
                                                    }
                                            }
                                            finally
                                            {
                                                #region clean-up temporary file

                                                try
                                                {
                                                    //clean-up temporary file
                                                    if (File.Exists(tempFile))
                                                    {
                                                        File.Delete(tempFile);
                                                    }
                                                }
                                                catch (Exception ex)
                                                {
                                                    Log(TraceEventType.Warning, "Error deleting temporary file {0} --> {1}: {2}", tempFile, ex.GetType(), ex.Message);
                                                    Log(TraceEventType.Information, ex.ToString().Replace(Environment.NewLine, " "));
                                                }

                                                #endregion
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            //on other exceptions, reset the report execution, and let the caller handle retry/recovery
                                            this.HistoryId = null;
                                            this.Data      = null;
                                            this.Error     = ex;
                                            this.ErrorCount++;
                                            this.EndTime = DateTime.Now;
                                            this.State   = ReportExecutionStateEnum.Failed;

                                            Log(TraceEventType.Information, "{0}: {1}", ex.GetType(), ex.Message);
                                            Log(TraceEventType.Information, "{0}", ex.ToString().Replace(Environment.NewLine, " "));
                                        }
                                    }

                                    //mark as successful
                                    this.HistoryId = historyId;
                                    this.Error     = null;
                                    this.EndTime   = DateTime.Now;
                                    this.State     = ReportExecutionStateEnum.Succeeded;
                                }
                                catch (WebException ex)
                                {
                                    this.HistoryId = null;
                                    this.Data      = null;
                                    this.Error     = ex;
                                    this.ErrorCount++;
                                    this.EndTime = DateTime.Now;
                                    this.State   = ReportExecutionStateEnum.Failed;

                                    Log(TraceEventType.Warning, "{0}: {1} --> An WebException was encountered when rendering {2}. See service logs for more details.", ex.GetType(), ex.Message, this.ReportPath);
                                    Log(TraceEventType.Information, ex.ToString().Replace(Environment.NewLine, " "));

                                    //on WebException, we need to check the web response for more details
                                    HandleWebException(ex);
                                    OnRenderCompleted();
                                }
                                catch (Exception ex)
                                {
                                    //on other exceptions, reset the report execution, and let the caller handle retry/recovery
                                    this.HistoryId = null;
                                    this.Data      = null;
                                    this.Error     = ex;
                                    this.ErrorCount++;
                                    this.EndTime = DateTime.Now;
                                    this.State   = ReportExecutionStateEnum.Failed;

                                    Log(TraceEventType.Information, "{0}: {1}", ex.GetType(), ex.Message);
                                    Log(TraceEventType.Information, ex.ToString().Replace(Environment.NewLine, " "));

                                    OnRenderCompleted();
                                }
                            }
                            finally
                            {
                                //raise completed event
                                if (!_cancelExecution)
                                {
                                    OnExecuteCompleted();
                                }
                            }
                        },
                            null);

                        #region logging

                        Log(TraceEventType.Information, "END BeginGetResponse()", rs.Url);

                        #endregion
                    }
                }

                #region exception handling

                catch (ReportExecutionException ex)
                {
                    //on custom ReportExecutionException, fail the report with an ErrorCode
                    this.HistoryId = null;
                    this.Data      = null;
                    this.ErrorCode = ex.ErrorCode;
                    this.Error     = ex;
                    this.ErrorCount++;
                    this.EndTime = DateTime.Now;
                    this.State   = ReportExecutionStateEnum.Failed;

                    //raise RenderCompleted event
                    OnRenderCompleted();
                    OnExecuteCompleted();

                    Log(TraceEventType.Information, "{0}: {1}", ex.GetType(), ex.Message);
                    Log(TraceEventType.Information, ex.ToString().Replace(Environment.NewLine, " "));
                }
                catch (Exception ex)
                {
                    //on other exceptions, reset the report execution, and let the caller handle retry/recovery
                    this.HistoryId = null;
                    this.Data      = null;
                    this.Error     = ex;
                    this.ErrorCount++;
                    this.EndTime = DateTime.Now;
                    this.State   = ReportExecutionStateEnum.Failed;

                    //raise RenderCompleted event
                    OnRenderCompleted();
                    OnExecuteCompleted();

                    Log(TraceEventType.Information, "{0}: {1}", ex.GetType(), ex.Message);
                    Log(TraceEventType.Information, ex.ToString().Replace(Environment.NewLine, " "));
                }

                #endregion
            }

            #region logging

            finally
            {
                Log(TraceEventType.Verbose, "END ExecuteAsync()");
            }

            #endregion
        }