/// <summary> /// main method that runs soap api, take a rdl in report server and change it. /// </summary> /// <param name="urlEndPoint">The report Server url.</param> /// <param name="inputReportPath">The path of input report file.</param> /// <param name="outputPath"> The path of output file.</param> /// <param name="downloadPath">The path to store original rdl and rds file.</param> /// <returns>the output file path.</returns> public string RunSoap(string urlEndPoint, string inputReportPath, string outputPath = "./", string downloadPath = "./testFiles/") { Directory.CreateDirectory(outputPath); Directory.CreateDirectory(downloadPath); string reportName = Path.GetFileNameWithoutExtension(inputReportPath); string outputFileName = Path.Combine(outputPath, reportName + ReportFileExtension); RdlFileIO rdlFileIO = new RdlFileIO(urlEndPoint); var rdlFilePath = rdlFileIO.DownloadRdl(inputReportPath, downloadPath); XElement[] dataSets = rdlFileIO.GetDataSets(inputReportPath, out Dictionary <string, XElement> referenceDataSetMap); DataSource[] dataSources = rdlFileIO.GetDataSources(inputReportPath); var dataSourceFilePath = Path.Combine(downloadPath, reportName + DataSourceFileExtension); var dataSetDirectoryPath = downloadPath + reportName + "_DataSets"; rdlFileIO.WriteDataSetContent(dataSets, dataSetDirectoryPath); rdlFileIO.WriteDataSourceContent(dataSources, dataSourceFilePath); ConvertFile(rdlFilePath, dataSources, referenceDataSetMap, outputPath); Console.WriteLine($"Conversion from {inputReportPath} to {outputFileName} Completed."); return(outputFileName); }
/// <summary> /// Takes a folder of reports, convert them and upload them to PBI workspace. /// </summary> /// <param name="urlEndPoint">the end point of report server.</param> /// <param name="inputPath">The Path of input Folder.</param> /// <param name="workspaceName">The name of requesting workspace.</param> /// <param name="clientID">The clientID of the App registered with permissions of Reading/Writing dataset, report and Reading Workspaces.</param> public void ConvertFolder(string urlEndPoint, string inputPath, string workspaceName, string clientID) { Trace("Starting the log-in window"); PowerBIClientWrapper powerBIPortal = new PowerBIClientWrapper(workspaceName, clientID); Trace("Log-in successfully, retrieving the reports..."); RdlFileIO rdlFileIO = new RdlFileIO(urlEndPoint); Trace($"Starting conversion and uploading the reports {DateTime.UtcNow.ToString()}"); if (!Directory.Exists("output")) { Directory.CreateDirectory("output"); } if (!rdlFileIO.IsFolder(inputPath)) { ConvertAndUploadReport( powerBIPortal, rdlFileIO, inputPath); } else { var reportPaths = rdlFileIO.GetReportsInFolder(inputPath); Console.WriteLine($"Found {reportPaths.Length} reports to convert"); Parallel.ForEach(reportPaths, reportPath => ConvertAndUploadReport( powerBIPortal, rdlFileIO, reportPath)); } }
private void ConvertAndUploadReport(PowerBIClientWrapper powerBIClient, RdlFileIO rdlFileIO, string reportPath) { var reportName = Path.GetFileName(reportPath); var report = rdlFileIO.DownloadRdl(reportPath); SaveAndCopyStream(reportName, report, $"output\\{reportName}_original.rdl"); if (powerBIClient.ExistReport(reportName)) { Trace($"CONFLICT : {reportName} A report with the same name already exists in the workspace"); } else { try { XElement[] dataSets = rdlFileIO.GetDataSets(reportPath, out Dictionary <KeyValuePair <string, string>, XElement> referenceDataSetMap); DataSource[] dataSources = rdlFileIO.GetDataSources(reportPath); var convertedFile = ConvertFile(reportPath, report, dataSources, referenceDataSetMap); SaveAndCopyStream(reportName, convertedFile, $"output\\{reportName}_convert.rdl"); powerBIClient.UploadRDL(reportName + ReportFileExtension, convertedFile); Trace($"SUCCESS : {reportName} The file is successfully uploaded"); } catch (HttpOperationException httpException) { string errorMessage; string requestId = String.Empty; if (httpException?.Response?.Headers.ContainsKey("RequestId") == true) { requestId = httpException.Response.Headers["RequestId"].First(); } if (httpException.Response.Headers.TryGetValue("X-PowerBI-Error-Details", out IEnumerable <string> returnedJsonStr)) { if (returnedJsonStr.Count() != 1) { Trace($"FAILED TO UPLOAD : {reportName} RequestId:{requestId} {httpException.Message}"); } else { string jsonString = returnedJsonStr.First(); var returnedJsonDetail = JObject.Parse(jsonString); errorMessage = returnedJsonDetail["error"]["pbi.error"]["details"][2]["detail"]["value"].Value <string>(); Trace($"FAILED TO UPLOAD : {reportName} RequestId:{requestId} {errorMessage}"); } } else { Trace($"FAILED TO UPLOAD : {reportName} RequestId:{requestId} {httpException.Message}"); } } catch (Exception e) { Trace($"FAILED : {reportName} {e.Message}"); } } }
/// <summary> /// take the rdl file, its dataSet and convert to a new file with Embedded dataSet. /// </summary> /// <param name="doc">The XDocument of rdl File.</param> /// <param name="dataSetMaps">Dict of Name-XElement Pair of dataSets used for conversion.</param> public void ConvertFileWithDataSet(string rdlfilePath, XDocument doc, Dictionary <DataSetReferenceNamePair, XElement> dataSetMaps) { var dataSetRootElememt = doc.Descendants(doc.Root.Name.Namespace + DataSetConstants.DataSets).FirstOrDefault(); if (dataSetRootElememt != null) { XNamespace currNamespace = doc.Root.Name.Namespace; var dataSetElements = dataSetRootElememt.Elements(); for (int i = dataSetElements.Count() - 1; i >= 0; i--) { var dataSetElement = dataSetElements.ElementAt(i); var datasetName = dataSetElement.Attribute("Name").Value; var sharedDataSetReferenceName = dataSetElement.Name.Namespace + DataSetConstants.SharedDataSetReference; if (dataSetElement.Descendants(sharedDataSetReferenceName).Count() == 1) { string datasetReference = dataSetElement.Descendants(sharedDataSetReferenceName).First().Value; var key = new DataSetReferenceNamePair(rdlfilePath, datasetName); XElement currDataSetNode = null; if (dataSetMaps.TryGetValue(key, out currDataSetNode)) { currDataSetNode = new XElement(currDataSetNode); // change passing by reference to by value, thus modification would not effect original dataSet ChangeNameSpaceHelper(currNamespace, currDataSetNode); var referenceNodes = currDataSetNode.Descendants(currDataSetNode.Name.Namespace + DataSetConstants.DataSourceReference); if (referenceNodes.Count() != 0) { string dataSetSourceName = RdlFileIO.SerializeDataSourceName(referenceNodes.ElementAt(0).Value); referenceNodes.ElementAt(0).ReplaceWith(new XElement(currDataSetNode.Name.Namespace + DataSetConstants.DataSourceName, dataSetSourceName)); } currDataSetNode.Attribute("Name").SetValue(datasetName); AlignParameters(dataSetElement, currDataSetNode); dataSetElement.Descendants(currNamespace + DataSetConstants.SharedDataSet).First().ReplaceWith(currDataSetNode.Descendants(currNamespace + DataSetConstants.Query).First()); if (dataSetElement.Descendants(currNamespace + DataSetConstants.Fields).Count() == 1 && currDataSetNode.Descendants(currNamespace + DataSetConstants.Fields).Count() == 1) { AlignCalculatedFields(dataSetElement.Descendants(currNamespace + DataSetConstants.Fields).First(), currDataSetNode.Descendants(currNamespace + DataSetConstants.Fields).First()); } AlignFilters(dataSetElement, currDataSetNode); } else { throw new Exception($"Can't find corresponding Data Set {datasetName}-{datasetReference}"); } } } } }
/// <summary> /// Takes a folder of reports, convert them and upload them to PBI workspace. /// </summary> /// <param name="urlEndPoint">the end point of report server.</param> /// <param name="inputPath">The Path of input Folder.</param> /// <param name="workspaceName">The name of requesting workspace.</param> /// <param name="clientID">The clientID of the App registered with permissions of Reading/Writing dataset, report and Reading Workspaces.</param> public void ConvertFolder(string urlEndPoint, string inputPath, string workspaceName, string clientID) { Trace("Starting the log-in window"); PowerBIClientWrapper powerBIClient = new PowerBIClientWrapper(workspaceName, clientID); Trace("Log-in successfully, retrieving the reports..."); rdlFileIO = new RdlFileIO(urlEndPoint); Trace($"Starting conversion and uploading the reports {DateTime.UtcNow.ToString()}"); if (!Directory.Exists("output")) { Directory.CreateDirectory("output"); } if (!rdlFileIO.IsFolder(inputPath)) { rootFolder = Path.GetDirectoryName(inputPath).Replace("\\", "/"); var reportName = Path.GetFileName(inputPath); reportNameMap.TryAdd(reportName, 1); reportPaths.Enqueue(inputPath); } else { rootFolder = inputPath; var rootReports = rdlFileIO.GetReportsInFolder(inputPath); Console.WriteLine($"Found {rootReports.Length} reports to convert"); foreach (string reportPath in reportPaths) { var reportName = Path.GetFileName(reportPath); reportNameMap.TryAdd(reportName, 1); } rootReports.ToList().ForEach(reportPaths.Enqueue); } while (reportPaths.Count > 0) { string reportPath = reportPaths.Dequeue(); ConvertAndUploadReport( powerBIClient, rdlFileIO, reportPath); } }