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; } } }
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 }