Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
micpol
Frequent Visitor

A working example of posting an RDL file wanted

I am working on posting a paginated report file into a workspace by means of Power BI REST API -https://docs.microsoft.com/en-us/rest/api/power-bi/imports/postimportingroup. The workspace is associated wth an A4 capacity, so it supports paginated reports. Since I am working on an application for 3rd party customers, the emebed reports approach is applied. This entails that an access token is retrieved basing on a client ID/secret and it is used then for communication over with Power BI service by the REST API.

 

While I am uploading a PBIX file no error is faced, however when I switch to a RDL file, I got this error:

 

"error":{"code":"RequestedFileIsEncryptedOrCorrupted","pbi.error":{"code":"RequestedFileIsEncryptedOrCorrupted","parameters":[],"details":[],"exceptionCulprit":1}}}

 

The URL, headers and body (I created an empty report for this test) look as below:

 

https://api.powerbi.com/v1.0/myorg/groups/[removed]/imports?datasetDisplayName=Paginated&nameConflict=Abort

Authorization: "Bearer [removed]"
Content-Type: "multipart/form-data; boundary=bbd44c43bfdb666aae510c2963f1f58a7df6f20172ee69c494ab549df1bf"

--bbd44c43bfdb666aae510c2963f1f58a7df6f20172ee69c494ab549df1bf
Content-Disposition: form-data; name="file"; filename="blank.rdl"
Content-Type: application/rdl

<?xml version="1.0" encoding="utf-8"?>
<Report MustUnderstand="df" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns:df="http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition/defaultfontfamily">
<rd:ReportUnitType>Mm</rd:ReportUnitType>
<rd:ReportID>852f90cd-e634-4063-9524-ee42e4b14caf</rd:ReportID>
<df:DefaultFontFamily>Segoe UI</df:DefaultFontFamily>
<AutoRefresh>0</AutoRefresh>
<ReportSections>
<ReportSection>
<Body>
<ReportItems>
<Textbox Name="ReportTitle">
<rd:WatermarkTextbox>Title</rd:WatermarkTextbox>
<rd:DefaultName>ReportTitle</rd:DefaultName>
<CanGrow>true</CanGrow>
<KeepTogether>true</KeepTogether>
<Paragraphs>
<Paragraph>
<TextRuns>
<TextRun>
<Value />
<Style>
<FontFamily>Segoe UI Light</FontFamily>
<FontSize>28pt</FontSize>
</Style>
</TextRun>
</TextRuns>
<Style />
</Paragraph>
</Paragraphs>
<Top>0mm</Top>
<Height>12.7mm</Height>
<Width>139.7mm</Width>
<Style>
<Border>
<Style>None</Style>
</Border>
<PaddingLeft>2pt</PaddingLeft>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
<PaddingBottom>2pt</PaddingBottom>
</Style>
</Textbox>
</ReportItems>
<Height>57.15mm</Height>
<Style>
<Border>
<Style>None</Style>
</Border>
</Style>
</Body>
<Width>152.4mm</Width>
<Page>
<PageFooter>
<Height>11.43mm</Height>
<PrintOnFirstPage>true</PrintOnFirstPage>
<PrintOnLastPage>true</PrintOnLastPage>
<ReportItems>
<Textbox Name="ExecutionTime">
<rd:DefaultName>ExecutionTime</rd:DefaultName>
<CanGrow>true</CanGrow>
<KeepTogether>true</KeepTogether>
<Paragraphs>
<Paragraph>
<TextRuns>
<TextRun>
<Value>=Globals!ExecutionTime</Value>
<Style />
</TextRun>
</TextRuns>
<Style>
<TextAlign>Right</TextAlign>
</Style>
</Paragraph>
</Paragraphs>
<Top>5.08mm</Top>
<Left>101.6mm</Left>
<Height>6.35mm</Height>
<Width>50.8mm</Width>
<Style>
<Border>
<Style>None</Style>
</Border>
<PaddingLeft>2pt</PaddingLeft>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
<PaddingBottom>2pt</PaddingBottom>
</Style>
</Textbox>
</ReportItems>
<Style>
<Border>
<Style>None</Style>
</Border>
</Style>
</PageFooter>
<PageHeight>29.7cm</PageHeight>
<PageWidth>21cm</PageWidth>
<LeftMargin>2cm</LeftMargin>
<RightMargin>2cm</RightMargin>
<TopMargin>2cm</TopMargin>
<BottomMargin>2cm</BottomMargin>
<ColumnSpacing>0.13cm</ColumnSpacing>
<Style />
</Page>
</ReportSection>
</ReportSections>
<ReportParametersLayout>
<GridLayoutDefinition>
<NumberOfColumns>4</NumberOfColumns>
<NumberOfRows>2</NumberOfRows>
</GridLayoutDefinition>
</ReportParametersLayout>
</Report>
--bbd44c43bfdb666aae510c2963f1f58a7df6f20172ee69c494ab549df1bf--

 

Does anyone have a working dump of of HTTP headers and body enabling to upload an RDL file successfuly into the Power BI serivce? I am coding this stuff in GO, hence the HTTP level fits me best.

 

I have also tried to use a PowerShell approach which I have found in Internet resources:

 

function Publish-PowerBIImport {

param (
[string]$Path,
[string]$GroupId
)

$powerBiBodyTemplate =
@'
--{0}
Content-Disposition: form-data; name="file"; filename="{1}"
Content-Type: application/rdl

{2}
--{0}--

'@

$fileName = [IO.Path]::GetFileName($Path)
$boundary = [guid]::NewGuid().ToString()
$fileBytes = [System.IO.File]::ReadAllBytes($Path)
$encoding = [System.Text.Encoding]::GetEncoding("utf-8")
$filebody = $encoding.GetString($fileBytes)
$body = $powerBiBodyTemplate -f $boundary, $fileName, $encoding.GetString($fileBytes)
$headers = @{
"Authorization" = "Bearer [removed]"
}

$url = "https://api.powerbi.com/v1.0/myorg/groups/$GroupId/imports?datasetDisplayName=$fileName&nameConflict=Abort"

Invoke-RestMethod -Uri $url -Method Post -Headers $headers -Body $body -ContentType "multipart/form-data; boundary=--$boundary"

}

$groupId = "[removed]"
$id = Publish-PowerBIImport -GroupId $groupId -Path "./file.rdl"

 
It work better, as the content seems to be processed. To confirm that I stopped the capacity for a while:
 
Invoke-RestMethod : {"error":{"code":"PaginatedReportCapacityStoppedOrNotFound","pbi.error":{"code":"PaginatedReportCapacityStoppedOrNotFound","parameters":{},"details":[{"code":"capacityObjectId","detail":{"type":1,"value":"[removed]"}}],"exceptionCulprit":1}}}

 

However, after restarting it, I got another UnknownError:

 

Invoke-RestMethod : {"error":{"code":"UnknownError","pbi.error":{"code":"UnknownError","parameters":{},"details":[],"exceptionCulprit":1}}}

 

Perhaps this means that the file data sent by the GO program is malformed.

 

I have also given a try to C#:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//Install-Package Microsoft.PowerBI.Api
using Microsoft.PowerBI.Api;
using Microsoft.PowerBI.Api.Models;
using System.IO;
using System.Threading;
using Microsoft.Rest;
namespace importPbix_PBIE

{
class Program
{
static string workspaceCollectionName = "Paginated";
static string workspaceId = "[removed]";
static string filePath = @"./blank.rdl";
static string accessToken = "[removed]";
static void Main(string[] args)
{
var credentials = new TokenCredentials(accessToken, "Bearer");
var client = new PowerBIClient(new Uri($"{"https://api.powerbi.com"}"), credentials);
using (var file = File.Open(filePath, FileMode.Open))
{
try {
var import = client.Imports.PostImportWithFileInGroup(new Guid(workspaceId), file, workspaceCollectionName, "Abort");
Console.WriteLine("{0}", import);
}
catch(Microsoft.Rest.HttpOperationException e) {
Console.WriteLine("{0} {1}",
e.Response.Content,
e.Response.StatusCode);
}
while (true) ;
}
}
}
}

 

unfortunatelly, the result is the same as in case of the 1st program in GO:

 

{"error":{"code":"RequestedFileIsEncryptedOrCorrupted","pbi.error":{"code":"RequestedFileIsEncryptedOrCorrupted","parameters":{},"details":[],"exceptionCulprit":1}}} BadRequest

 

A working HTTP flow or any ideas would be appreciated.

 

--

Michal

 

2 REPLIES 2
fandrusi
New Member

Update: I returned to this issue and the import is working without error!  I'm using the C# POST.  Part of my issue was I'm POSTing an RDL and the only acceptable conflict" param values are "Abort" and "Overwrite", this isn't obvious in all instances of the docu, but it is there.  Passing something else returns a non-specific error.

 

(Aside: Unfortunately there's no good "Upsert" option, you have to know if the file exists in the destination directory before you make the call.)

 

In the OP C# example the problem might be the file isn't be passed in the proper format.  In my situation I'm GETting an RDL then POSTing it back.  I GET the file from azure source workspace into a string to manipulate it then POST it.

 

The wrapper client call will package the file in the proper Form-Data structure for the Rest call.

 

This C# works (GET then POST)

 

string localRdl

HttpOperationResponse<Stream> getResponse = await client.Reports.ExportReportInGroupWithHttpMessagesAsync([workspace Id], [report Id]);

if (getResponse.Response.StatusCode == HttpStatusCode.OK)
{
    var stream = getResponse.Response.Content.ReadAsStreamAsync();

    StreamReader reader = new StreamReader(stream.Result);
    localRdl = reader.ReadToEnd();
}

...
...

MemoryStream ms = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(localRdl));

HttpOperationResponse<Import> postResponse = await client.Imports.PostImportFileWithHttpMessage([Workspace ID], ms, [report name], "Abort");

if (postResponse.Response.StatusCode == HttpStatusCode.Accepted)
{
    /* all good */
}

 

fandrusi
New Member

Having the identical problem.   It's odd that there's a PowerBI client which makes it very easy to pull down .RDLs but submitting them feels nearly impossible.  I figure there must be a wrapper for the content prep somplace, otherwise it's pretty difficult to deal with.

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.