Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
4 years ago

Operation returned an invalid status code 'Unauthorized' at GetReportInGroupWithHttpMessagesAsync

Hi v-chenwuz-msft , Anonymous 

I am getting errors when embedding a power bi report into a web application.

My organization's IT Team configure an Azure App and Service Principal with grant the Power BI Service for authentication and provided me ApplicationName, ClientId, ClientSecret, and TenantId. I integrated embed with customer functionality with sample code (Power BI .Net Core). In appsettings.json, I have changed clientID, clientSecret, tenantID, workspaceID, reportID and authentication mode as 'ServicePrincipal'. Still got an Unauthorized error.

 

Error statement -

Operation returned an invalid status code 'Unauthorized'
at Microsoft.PowerBI.Api.ReportsOperations.GetReportInGroupWithHttpMessagesAsync(Guid groupId, Guid reportId, Dictionary`2 customHeaders, CancellationToken cancellationToken)
at Microsoft.PowerBI.Api.ReportsOperationsExtensions.GetReportInGroupAsync(IReportsOperations operations, Guid groupId, Guid reportId, CancellationToken cancellationToken)
at Microsoft.PowerBI.Api.ReportsOperationsExtensions.GetReportInGroup(IReportsOperations operations, Guid groupId, Guid reportId)
at AppOwnsData.Services.PbiEmbedService.GetEmbedParams(Guid workspaceId, Guid reportId, Guid additionalDatasetId) in D:\Download\New\PowerBI-Developer-Samples\PowerBI-Developer-Samples-master\.NET Core\Embed for your customers\AppOwnsData\Services\PbiEmbedService.cs:line 49
at AppOwnsData.Controllers.EmbedInfoController.GetEmbedInfo() in D:\Download\New\PowerBI-Developer-Samples\PowerBI-Developer-Samples-master\.NET Core\Embed for your customers\AppOwnsData\Controllers\EmbedInfoController.cs:line 45

 

Simple, ASP.Net Core App

 

index.js

// ----------------------------------------------------------------------------
// 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.Aad,
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);
}
});
});

 

EmbeddedInfoController.cs

public class EmbedInfoController : Controller
{
private readonly PbiEmbedService pbiEmbedService;
private readonly IOptions<AzureAd> azureAd;
private readonly IOptions<PowerBI> powerBI;

public EmbedInfoController(PbiEmbedService pbiEmbedService, IOptions<AzureAd> azureAd, IOptions<PowerBI> powerBI)
{
this.pbiEmbedService = pbiEmbedService;
this.azureAd = azureAd;
this.powerBI = powerBI;
}

/// <summary>
/// Returns Embed token, Embed URL, and Embed token expiry to the client
/// </summary>
/// <returns>JSON containing parameters for embedding</returns>
[HttpGet]
public string GetEmbedInfo()
{
try
{
// Validate whether all the required configurations are provided in appsettings.json
string configValidationResult = ConfigValidatorService.ValidateConfig(azureAd, powerBI);
if (configValidationResult != null)
{
HttpContext.Response.StatusCode = 400;
return configValidationResult;
}

EmbedParams embedParams = pbiEmbedService.GetEmbedParams(new Guid(powerBI.Value.WorkspaceId), new Guid(powerBI.Value.ReportId));
return JsonSerializer.Serialize<EmbedParams>(embedParams);
}
catch (Exception ex)
{
HttpContext.Response.StatusCode = 500;
return ex.Message + "\n\n" + ex.StackTrace;
}
}
}

 

PbiEmbedService.cs

public class PbiEmbedService
{
private readonly AadService aadService;
private readonly string urlPowerBiServiceApiRoot = "https://api.powerbi.com";

public PbiEmbedService(AadService aadService)
{
this.aadService = aadService;
}

/// <summary>
/// Get Power BI client
/// </summary>
/// <returns>Power BI client object</returns>
public PowerBIClient GetPowerBIClient()
{
var tokenCredentials = new TokenCredentials(aadService.GetAccessToken(), "Bearer");
return new PowerBIClient(new Uri(urlPowerBiServiceApiRoot), tokenCredentials);
}

/// <summary>
/// Get embed params for a report
/// </summary>
/// <returns>Wrapper object containing Embed token, Embed URL, Report Id, and Report name for single report</returns>
public EmbedParams GetEmbedParams(Guid workspaceId, Guid reportId, [Optional] Guid additionalDatasetId)
{
PowerBIClient pbiClient = this.GetPowerBIClient();

var client = JsonSerializer.Serialize(pbiClient);

// Get report info
var pbiReport = pbiClient.Reports.GetReportInGroup(workspaceId, reportId);

// Check if dataset is present for the corresponding report
// If isRDLReport is true then it is a RDL Report
var isRDLReport = String.IsNullOrEmpty(pbiReport.DatasetId);

EmbedToken embedToken;

// Generate embed token for RDL report if dataset is not present
if (isRDLReport)
{
// Get Embed token for RDL Report
embedToken = GetEmbedTokenForRDLReport(workspaceId, reportId);
}
else
{
// Create list of datasets
var datasetIds = new List<Guid>();

// Add dataset associated to the report
datasetIds.Add(Guid.Parse(pbiReport.DatasetId));

// Append additional dataset to the list to achieve dynamic binding later
if (additionalDatasetId != Guid.Empty)
{
datasetIds.Add(additionalDatasetId);
}

// Get Embed token multiple resources
embedToken = GetEmbedToken(reportId, datasetIds, workspaceId);
}

// Add report data for embedding
var embedReports = new List<EmbedReport>() {
new EmbedReport
{
ReportId = pbiReport.Id, ReportName = pbiReport.Name, EmbedUrl = pbiReport.EmbedUrl
}
};

// Capture embed params
var embedParams = new EmbedParams
{
EmbedReport = embedReports,
Type = "Report",
EmbedToken = embedToken
};

return embedParams;
}

/// <summary>
/// Get embed params for multiple reports for a single workspace
/// </summary>
/// <returns>Wrapper object containing Embed token, Embed URL, Report Id, and Report name for multiple reports</returns>
/// <remarks>This function is not supported for RDL Report</remakrs>
public EmbedParams GetEmbedParams(Guid workspaceId, IList<Guid> reportIds, [Optional] IList<Guid> additionalDatasetIds)
{
// Note: This method is an example and is not consumed in this sample app

PowerBIClient pbiClient = this.GetPowerBIClient();

// Create mapping for reports and Embed URLs
var embedReports = new List<EmbedReport>();

// Create list of datasets
var datasetIds = new List<Guid>();

// Get datasets and Embed URLs for all the reports
foreach (var reportId in reportIds)
{
// Get report info
var pbiReport = pbiClient.Reports.GetReportInGroup(workspaceId, reportId);

datasetIds.Add(Guid.Parse(pbiReport.DatasetId));

// Add report data for embedding
embedReports.Add(new EmbedReport { ReportId = pbiReport.Id, ReportName = pbiReport.Name, EmbedUrl = pbiReport.EmbedUrl });
}

// Append to existing list of datasets to achieve dynamic binding later
if (additionalDatasetIds != null)
{
datasetIds.AddRange(additionalDatasetIds);
}

// Get Embed token multiple resources
var embedToken = GetEmbedToken(reportIds, datasetIds, workspaceId);

// Capture embed params
var embedParams = new EmbedParams
{
EmbedReport = embedReports,
Type = "Report",
EmbedToken = embedToken
};

return embedParams;
}

/// <summary>
/// Get Embed token for single report, multiple datasets, and an optional target workspace
/// </summary>
/// <returns>Embed token</returns>
/// <remarks>This function is not supported for RDL Report</remakrs>
public EmbedToken GetEmbedToken(Guid reportId, IList<Guid> datasetIds, [Optional] Guid targetWorkspaceId)
{
PowerBIClient pbiClient = this.GetPowerBIClient();

// 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(reportId) },

datasets: datasetIds.Select(datasetId => new GenerateTokenRequestV2Dataset(datasetId.ToString())).ToList(),

targetWorkspaces: targetWorkspaceId != Guid.Empty ? new List<GenerateTokenRequestV2TargetWorkspace>() { new GenerateTokenRequestV2TargetWorkspace(targetWorkspaceId) } : null
);

// Generate Embed token
var embedToken = pbiClient.EmbedToken.GenerateToken(tokenRequest);

return embedToken;
}

/// <summary>
/// Get Embed token for multiple reports, datasets, and an optional target workspace
/// </summary>
/// <returns>Embed token</returns>
/// <remarks>This function is not supported for RDL Report</remakrs>
public EmbedToken GetEmbedToken(IList<Guid> reportIds, IList<Guid> datasetIds, [Optional] Guid targetWorkspaceId)
{
// Note: This method is an example and is not consumed in this sample app

PowerBIClient pbiClient = this.GetPowerBIClient();

// Convert report Ids to required types
var reports = reportIds.Select(reportId => new GenerateTokenRequestV2Report(reportId)).ToList();

// Convert dataset Ids to required types
var datasets = datasetIds.Select(datasetId => new GenerateTokenRequestV2Dataset(datasetId.ToString())).ToList();

// Create a request for getting Embed token
// This method works only with new Power BI V2 workspace experience
var tokenRequest = new GenerateTokenRequestV2(

datasets: datasets,

reports: reports,

targetWorkspaces: targetWorkspaceId != Guid.Empty ? new List<GenerateTokenRequestV2TargetWorkspace>() { new GenerateTokenRequestV2TargetWorkspace(targetWorkspaceId) } : null
);

// Generate Embed token
var embedToken = pbiClient.EmbedToken.GenerateToken(tokenRequest);

return embedToken;
}

/// <summary>
/// Get Embed token for multiple reports, datasets, and optional target workspaces
/// </summary>
/// <returns>Embed token</returns>
/// <remarks>This function is not supported for RDL Report</remakrs>
public EmbedToken GetEmbedToken(IList<Guid> reportIds, IList<Guid> datasetIds, [Optional] IList<Guid> targetWorkspaceIds)
{
// Note: This method is an example and is not consumed in this sample app

PowerBIClient pbiClient = this.GetPowerBIClient();

// Convert report Ids to required types
var reports = reportIds.Select(reportId => new GenerateTokenRequestV2Report(reportId)).ToList();

// Convert dataset Ids to required types
var datasets = datasetIds.Select(datasetId => new GenerateTokenRequestV2Dataset(datasetId.ToString())).ToList();

// Convert target workspace Ids to required types
IList<GenerateTokenRequestV2TargetWorkspace> targetWorkspaces = null;
if (targetWorkspaceIds != null)
{
targetWorkspaces = targetWorkspaceIds.Select(targetWorkspaceId => new GenerateTokenRequestV2TargetWorkspace(targetWorkspaceId)).ToList();
}

// Create a request for getting Embed token
// This method works only with new Power BI V2 workspace experience
var tokenRequest = new GenerateTokenRequestV2(

datasets: datasets,

reports: reports,

targetWorkspaces: targetWorkspaceIds != null ? targetWorkspaces : null
);

// Generate Embed token
var embedToken = pbiClient.EmbedToken.GenerateToken(tokenRequest);

return embedToken;
}

/// <summary>
/// Get Embed token for RDL Report
/// </summary>
/// <returns>Embed token</returns>
public EmbedToken GetEmbedTokenForRDLReport(Guid targetWorkspaceId, Guid reportId, string accessLevel = "view")
{
PowerBIClient pbiClient = this.GetPowerBIClient();

// Generate token request for RDL Report
var generateTokenRequestParameters = new GenerateTokenRequest(
accessLevel: accessLevel
);

// Generate Embed token
var embedToken = pbiClient.Reports.GenerateTokenInGroup(targetWorkspaceId, reportId, generateTokenRequestParameters);

return embedToken;
}
}

3 Replies