Could not pass custom parameters while loading paginated reports in powerbi javascript api - powerbi

Goal: Load a paginated report into webpage which has few parameters with the help of powerbi api javascript.
Paginated reportUrl:
https://app.powerbi.com/groups/workspaceId/rdlreports/reportId?ctid=something&rp:CustomerID=something&rp:ContractID=something
I can load the report but could not pass the parameters - hence report is loading as blank.
UnLike powerbi report, paginated report doesn't support report.getFilters() like powerBi embedded report.
I referred these docs - but could not find any help...
https://learn.microsoft.com/en-us/power-bi/paginated-reports-parameters
https://learn.microsoft.com/en-us/power-bi/developer/paginated-reports-row-level-security#passing-the-configured-parameter-using-the-embed-token
https://learn.microsoft.com/en-us/power-bi/developer/embed-paginated-reports-customers
This is how I am getting a powerbi report and then embeding that in webpage:
[HttpGet]
[Route("AccessToken")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult> GetEmbeddedAccessTokenAsync(string reportType)
{
Guid currentReportId = getCurrentReportId(reportType); //private method which gets the report guid
using (var client = await GetPowerBIClientAsync())
{
var report = await client.Reports.GetReportInGroupAsync(_powerBiWorkspaceId, currentReportId);
var generateTokenRequestParameters = new GenerateTokenRequest(accessLevel: TokenAccessLevel.View);
var tokenResponse = await client.Reports.GenerateTokenInGroupAsync(_powerBiWorkspaceId, report.Id, generateTokenRequestParameters);
return new OkObjectResult(JsonSerializer.Serialize(new { EmbedUrl = report.EmbedUrl, AccessToken = tokenResponse.Token, WorkspaceId = _powerBiWorkspaceId, ReportId = report.Id, Expires = tokenResponse.Expiration }));
}
}
let token = await this.http.get(this.url + 'api/PowerBi/AccessToken?reportType=' + this.reportType, { params: {}, responseType: 'text', withCredentials: true }).toPromise();
let tokenObject = JSON.parse(token);
let reportContainer = document.getElementById('kpi-report-container');
this.powerbi.bootstrap(reportContainer, config);
let report: Report = <Report>(this.powerbi.embed(reportContainer, config));
// Report.off removes a given event handler if it exists.
report.off("loaded");
let self = this;
// Report.on will add an event handler which prints to Log window.
report.on("loaded", function () {
self.SelectedReportId(self.reportId);
report.updateSettings({
bookmarksPaneEnabled: false,
filterPaneEnabled: true
});
// Set token expiration listener
self.SetTokenExpirationListener(tokenObject.Expires,
2, /*minutes before expiration*/
tokenObject.ReportId,
tokenObject.WorkspaceId);
});

We can pass the URL parameters into an embedded Paginated Report by concatenating the parameters with the embed URL.
For example:
If we have a parameter named "Salesperson" which has one of its values as "Brownie", then we can filter the Paginated report by concatenating it in the embed URL of the report within report config:
embedUrl + "&rp:Salesperson=Brownie"
The above embedUrl will filter the embedded paginated report as per the given parameter.
You can refer this blog link for more information.

Related

How to Embed 2 or more Power BI reports in a Single web page?

I have a standard user owns sample application which can embed 1 report at a time, however, I need to embed 2 or more reports in a single web page. If there is a sample solution file that can do this Job, that's great.
To embed Power BI element using the JavaScript client, you must configure the settings (which report/dashboard/tile to be embedded, how to authorize the request, what view mode, provide additional filters, etc.) and then call the embed method passing the configuration and a <div> element where the embedded element will be loaded.
This code is from the sample:
// ----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// ----------------------------------------------------------------------------
$(function () {
var models = window["powerbi-client"].models;
var reportContainer = $("#report-container").get(0);
$.ajax({
type: "GET",
url: "/embedinfo/getembedinfo",
success: function (data) {
embedParams = $.parseJSON(data);
reportLoadConfig = {
type: "report",
tokenType: models.TokenType.Embed,
accessToken: embedParams.EmbedToken.Token,
// You can embed different reports as per your need
embedUrl: embedParams.EmbedReport[0].EmbedUrl,
// Enable this setting to remove gray shoulders from embedded report
// settings: {
// background: models.BackgroundType.Transparent
// }
};
// Use the token expiry to regenerate Embed token for seamless end user experience
// Refer https://aka.ms/RefreshEmbedToken
tokenExpiry = embedParams.EmbedToken.Expiration;
// Embed Power BI report when Access token and Embed URL are available
var report = powerbi.embed(reportContainer, reportLoadConfig);
// Clear any other loaded handler events
report.off("loaded");
// Triggers when a report schema is successfully loaded
report.on("loaded", function () {
console.log("Report load successful");
});
// Clear any other rendered handler events
report.off("rendered");
// Triggers when a report is successfully embedded in UI
report.on("rendered", function () {
console.log("Report render successful");
});
// Clear any other error handler events
report.off("error");
// Handle embed errors
report.on("error", function (event) {
var errorMsg = event.detail;
// Use errorMsg variable to log error in any destination of choice
console.error(errorMsg);
return;
});
},
error: function (err) {
// Show error container
var errorContainer = $(".error-container");
$(".embed-container").hide();
errorContainer.show();
// Format error message
var errMessageHtml = "<strong> Error Details: </strong> <br/>" + err.responseText;
errMessageHtml = errMessageHtml.split("\n").join("<br/>");
// Show error message on UI
errorContainer.append(errMessageHtml);
}
});
});
So to be able to embed multiple elements, you must prepare multiple configurations (see reportLoadConfig in the sample code), prepare multiple placeholders (see reportContainer in the sample code) and call powerbi.embed multiple times.
Check again this article - Understanding the different embedding solutions. For your tests you can use the developer sandbox in the Power BI playground.

How to bind multiple Power BI datasets to a single Power BI Report

I have a user name logging into the Web Application.
I am using HTML, CSS, JavaScript and ASP.NET webform to run the Web Application with Power BI embedded reports.
I am trying to code to pass Server Name and Database name based on the user logged in to Power BI embedded config.
How to pass server name and database name to Power BI Embedded config?
Tried to test the application flow with Import Data Sets using following things, but the Power BI Report is not getting loaded in HTML div element. Its giving "Power BI Loading logo" in the embed div and then showing message as "Power BI content is not available"
Application Flow:
Power BI workspace has One Report and Two Datasets
Following is the Token generation code in .NET
// Generate an embed token and populate embed variables
using (var client = new PowerBIClient(new Uri(Configurations.ApiUrl), Authentication.GetTokenCredentials()))
//using (var client = new PowerBIClient(new Uri(Configurations.ApiUrl), Authentication.m_tokenCredentials))
{
var report = client.Reports.GetReportInGroup(new Guid(Configurations.WorkspaceId), new Guid(ddlReport.SelectedValue));
var rls = new EffectiveIdentity(username: appLoginUserName, new List<string> { userDatasetId.ToString() });
// Effective Identity
var rolesList = new List<string>();
rolesList.Add("Tenant");
rls.Roles = rolesList;
// Create list of datasets
var v2DatasetID = new List<Guid>();
v2DatasetID.Add(userDatasetId);
// Create list of Effective Identities
var v2rls = new List<EffectiveIdentity>();
v2rls.Add(rls);
// Create a request for getting Embed token
// This method works only with new Power BI V2 workspace experience
var tokenRequest = new GenerateTokenRequestV2(
reports: new List<GenerateTokenRequestV2Report>() { new GenerateTokenRequestV2Report(report.Id) },
datasets: v2DatasetID.Select(datasetId => new GenerateTokenRequestV2Dataset(datasetId.ToString())).ToList(),
identities: v2rls,
targetWorkspaces: null
);
// Generate Embed token
var getToken = client.EmbedToken.GenerateToken(tokenRequest);
// Populate embed variables (to be passed client-side)
//embedToken = tokenResponse.Token;
embedToken = getToken.ToString();
embedUrl = report.EmbedUrl;
reportId = report.Id;
}
Following is the Power BI embed configuration with dynamic dataset:
<script>
// Read embed token
var embedToken = "<% =this.embedToken %>";
// Read embed URL
var embedUrl = "<% = this.embedUrl %>";
// Read report Id
var reportId = "<% = this.reportId %>";
// Read dataset Id
var userDatasetId = "<% = this.userDatasetId %>";
// Get models (models contains enums)
var models = window['powerbi-client'].models;
// Embed configuration is used to describe what and how to embed
// This object is used when calling powerbi.embed
// It can also includes settings and options such as filters
var config = {
type: 'report',
tokenType: models.TokenType.Embed,
accessToken: embedToken,
embedUrl: embedUrl,
id: reportId,
datasetId: userDatasetId, // The dataset id that you want the report to use
settings: {
filterPaneEnabled: true,
navContentPaneEnabled: true,
extensions: [
{
command: {
name: "cmdShowValue",
title: "Show Value in MessageBox",
selector: {
$schema: "http://powerbi.com/product/schema#visualSelector",
visualName: "VisualContainer7" // Sales and Avg Price by Month visual
},
extend: {
visualContextMenu: {
title: "Show Value in MessageBox"
}
}
}
}
]
}
};
// Embed the report within the div element
var report = powerbi.embed(embedDiv, config);
</script>
This is not possible. These are report wide settings and you are asking how two different users, which are viewing the same report simultaneously, to connect to a different data sources. You must either deploy as many report are needed and choose which one to embed, or build one report using all the data sources, and then filter the data based on the currently logged in used.
Otherwise, the direct answer to your question is to rebind the report or to change the datasource of the dataset.

What do I place as the report id in the PowerBIEmbed when creating a new report?

I'm trying to use the PowerBIEmbed React component to create and design a new report. Everything works great when I edit an existing report, but when I'm creating a new one (using an embed token generated with TokenAccessLevel.Create), I'm getting the following error:
Report id is required, but it was not found. You must provide an id either as part of embed configuration or as attribute 'powerbi-report-id'.
The id I'm passing in via the configuration is the empty GUID ("00000000-0000-0000-0000-000000000000"). I have also tried deleting that property from the configuration.
I have the permissions set to models.Permissions.All (which includes models.Permissions.Create), so that isn't the issue.
Client code
const config = {
permissions: models.Permissions.All,
tokenType: models.TokenType.Embed,
type: 'report',
embedURL: generatedURL,
accessToken: generatedToken,
viewMode: models.ViewMode.Edit,
};
return (
<PowerBIEmbed
embedConfig={config}
getEmbeddedComponent={report => this.setState({ report })}
/>
);
Server Code
var authToken = await PowerBIAuthentication.DoAuthentication(_Config);
using var client = new PowerBIClient(new Uri(_Config.ApiUrl), authToken);
var dataSets = await client.Datasets.GetDatasetsInGroupAsync(_Config.WorkspaceId, cancellationToken);
var dataSet = dataSets.Value.First(x => x.Name == "AppProtoModel");
var embedTokenParameters = new GenerateTokenRequest(TokenAccessLevel.Create, dataSet.Id);
var embedToken = await client.Reports.GenerateTokenForCreateInGroupAsync(
_Config.WorkspaceId,
embedTokenParameters,
cancellationToken: cancellationToken);
myDoc.PowerBISettings.EmbedToken = embedToken;
myDoc.PowerBISettings.EmbedUrl = dataSet.CreateReportEmbedURL;
return myDoc;
Currently, PowerBIEmbed component from powerbi-client-react library does not support create mode embedding for Power BI Report and, it can be achieved using Power BI JS SDK.
Refer below code snippets:
const embedConfiguration: IEmbedConfiguration = {
permissions: models.Permissions.All,
tokenType: models.TokenType.Embed,
type: "report",
embedUrl: createReportEmbedURL,
accessToken: createEmbedToken,
viewMode: models.ViewMode.Edit,
datasetId: datasetId,
};
const report = powerbi.createReport(reportContainer, embedConfiguration);
createReportEmbedURL mentioned in above snippet can be generated using Datasets - Get Dataset API.
createEmbedToken mentioned in above snippet can be generated using Embed Token - Report GenerateTokenForCreateInGroup API.
Note: The datasetId passed in the configuration should be the same which is used to generate createReportEmbedURL.
Refer following docs for more information:
Create and save embedded report

powerbi global object not found in typescript

I am trying to use this power bi below code where powerbi object not found error is getting in my typescript code:
// Read embed application token from textbox
var txtAccessToken = $('#txtAccessToken').val();
// Read embed URL from textbox
var txtEmbedUrl = $('#txtReportEmbed').val();
// Read report Id from textbox
var txtEmbedReportId = $('#txtEmbedReportId').val();
// Read embed type from radio
var tokenType = $('input:radio[name=tokenType]:checked').val();
// Get models. models contains enums that can be used.
var models = window['powerbi-client'].models;
// We give All permissions to demonstrate switching between View and Edit mode and saving report.
var permissions = models.Permissions.All;
// Embed configuration used to describe the what and how to embed.
// This object is used when calling powerbi.embed.
// This also includes settings and options such as filters.
// You can find more information at https://github.com/Microsoft/PowerBI-JavaScript/wiki/Embed-Configuration-Details.
var config= {
type: 'report',
tokenType: tokenType == '0' ? models.TokenType.Aad : models.TokenType.Embed,
accessToken: txtAccessToken,
embedUrl: txtEmbedUrl,
id: txtEmbedReportId,
permissions: permissions,
settings: {
filterPaneEnabled: true,
navContentPaneEnabled: true
}
};
// Get a reference to the embedded report HTML element
var embedContainer = $('#embedContainer')[0];
// Embed the report and display it within the div container.
var report = powerbi.embed(embedContainer, config);
// Report.off removes a given event handler if it exists.
report.off("loaded");
// Report.on will add an event handler which prints to Log window.
report.on("loaded", function() {
Log.logText("Loaded");
});
report.on("error", function(event) {
Log.log(event.detail);
report.off("error");
});
report.off("saved");
report.on("saved", function(event) {
Log.log(event.detail);
if(event.detail.saveAs) {
Log.logText('In order to interact with the new report, create a new token and load the new report');
}
});
in the above code the powerbi object shows not found in my typescript code: powerbi.embed(embedContainer, config);
I tried to use window['powerbi'] or window.powerbi but doesn't work. What should be the solution then?
I faced a similar issue a few weeks back (probably exactly the same). For me it seems that what works is using window.powerbi.embed() for the embed action, whereas the import import * as powerbi from "powerbi-client"; is used for all other Power BI objects.
I had the same problem, found this question through a google search. I wasn't able to figure out why it wasn't on the window, but as a work around you can initialize it yourself like this:
import * as pbi from "powerbi-client";
const powerbi = new pbi.service.Service(
pbi.factories.hpmFactory,
pbi.factories.wpmpFactory,
pbi.factories.routerFactory
);
const container = document.getElementById("report-container");
powerbi.embed(container, embedConfiguration);

Power BI embed error 403 forbidden error from server

I'm following the steps mentioned in the power BI community here and testing it out in Postman and have completed first 4 steps. However on testing the embed code in Microsoft Power BI Embedded Playground, i keep getting following error :
{
"message": "LoadReportFailed",
"detailedMessage": "Fail to initialize - Could not resolve cluster",
"errorCode": "403",
"level": 6,
"technicalDetails": {
"requestId": "57679585-022b-4871-ae6d-bb722d4a07cc"
}
}
Also, when trying the alternative, HTML setup provided in STEP 5, i again keep getting 403 error stating : "GET https://wabi-india-west-redirect.analysis.windows.net/powerbi/globalservice/v201606/clusterdetails 403 (Forbidden)"
Please help. I've been trying to get this thing to work for over a week now.
It turns out that though i had workspace ID, client ID, report ID and though i was making proper calls to the API, the error in the fifth step was because i was a member of the the workspace where my reports were.
For API to work, you need to be the admin of the workspace from which you are trying to get the reports
This issues I fixed finally using below steps.
For embed the power BI reports in front end (angular/ JS) you have to generate 2 different tokens (for app-only scenario).
Access token using master account details /service principal account
( this is used to connect with power BI server)
Embed token (can be generated using access token & .NET Power BI rest API's).
Step1 : Access Token generation
PBIClientId": "xxxxxx-xxx-xxxx-xxxx-xxxxxxxxx",
"PBIClientSecret": "<client secret>",
"PBIApiUrl": "https://api.powerbi.com/",
"ResourceUrl": "https://analysis.windows.net/powerbi/api",
"AuthorityUrl": "https://login.windows.net/common/",
"TenantId": "<TenantId>",
private async Task<string> GeneratePowerBIAccessToken()
{
var tenantSpecificURL = authorityUrl.Replace("common", tenantId);
var authenticationContext = new AuthenticationContext(tenantSpecificURL);
// Authentication using app credentials
var credential = new ClientCredential(clientId, clientSecret);
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(resourceUrl, credential);
return authenticationResult.AccessToken;
}
Step2: Get Power BI Report Embed URL
Pass access token which is generated in step1, groupId and reportId you get from power BI portal url.
private async Task<EmbedModel> GetEmbedReportModel(string groupId, string reportId, string accessToken)
{
string restUrl = "https://api.powerbi.com/v1.0/myorg/groups/" + groupId+"/reports";
// add JSON to HttpContent object and configure content type
var method = new HttpMethod("GET");
var request = new HttpRequestMessage(method, restUrl);
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
// send POST request to Power BI service
var jsonResult = await client.SendAsync(request).Result.Content.ReadAsStringAsync();
var reportObject = JsonConvert.DeserializeObject<ReportObjects>(jsonResult);
var report = reportObject.value.Where(r => r.id == reportId).FirstOrDefault();
return new EmbedModel { Id = report.id, EmbedUrl = report.embedUrl, Name = report.name };
}
}
the response you will get here is
{
"value": [
{
"datasetId": "xxxxxx-abcasdasd-dasda-4weas",
"id": "3asder78-asds-4d73-1232-5345dfsdfs",
"name": "SalesMarketing",
"webUrl": "https://app.powerbi.com/groups/xxx-xxxxx-xxx-xxxxxx-xxxxx/reports/xxxxxx-xxxx-xxx-xxxx-xxxxxxxx",
"embedUrl": "https://app.powerbi.com/reportEmbed?reportId=xxxxxx-xxxx-xxxx-xxxx-xxxxxx&groupId=aadasda21-xxcx-xx-xx-xxxxxx"
}
]
}
step 3: Call generate embed token API
private async Task<EmbedToken> GenerateEmbedToken(string groupId, string reportId,string accessToken)
{
string apiURL = "https://api.powerbi.com/v1.0/myorg/groups/"+ groupId + "/reports/"+ reportId +"/GenerateToken";
string requestBody = #"{ ""accessLevel"": ""View""}";
HttpContent postRequestBody = new StringContent(requestBody);
postRequestBody.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
// prepare PATCH request
var method = new HttpMethod("POST");
var request = new HttpRequestMessage(method, apiURL);
request.Content = postRequestBody;
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
// send POST request to Power BI service
var jsonResult = await client.SendAsync(request).Result.Content.ReadAsStringAsync();
EmbedToken embedToken = JsonConvert.DeserializeObject<EmbedToken>(jsonResult);
return embedToken;
}
}
Step 4: Use embed token and embed url in front end app
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
<script src="powerbi.min.js" type="text/javascript"> </script>
<script type="text/javascript">
window.onload = function () {
var models = window['powerbi-client'].models;
var embedConfiguration = {
type: 'report',
id:'537887ee-7c7c-43c6-850b-9293f60aa3f3',
accessToken: 'H4sIAAAAAAAEAB3Tt66EV.....phVP_a_5F15fA_FCBQAA',
embedUrl: 'https://app.powerbi.com/reportEmbed?reportId=2376660ee-1c2c-16c6-980b-923260aa3f3&groupId=2adeaaa-xxxx-xxxx-xxxx-8d13b04c6e0e&w=2&config=eyJjbHVzdGVyV.....',
permissions: models.Permissions.All,
tokenType: models.TokenType.Embed,
viewMode:models.ViewMode.View,
};
var $reportContainer = $('#dashboardContainer');
var report = powerbi.embed($reportContainer.get(0), embedConfiguration);
}
</script>
<div id="dashboardContainer"></div>
</html>
Change all values before you run this.
Please make sure you are sending correct Token in the authorization header. Make sure you use "Bearer " as Authorization header.
Also, make sure your user has all required permissions.