Power BI Embedded - 将报表保存到不同的工作区会导致错误
Power BI Embedded - saving report to different workspace results in error
我在 PowerBI embedded 中跨不同工作区保存报表时遇到问题。对于背景:
- 我们正在使用嵌入到 App Owns Data 场景中的 PowerBI
- 我们正在运行 SaaS、多租户单一数据库方法,我们使用 RLS 在 PowerBI 中分离租户数据
- 我们正在使用将在多个工作区之间共享的单一数据集(根据 Microsoft 文档,我相信 V2 工作区支持它)
- 服务主体的范围定义正确,我们购买并配置了专用容量
- 我们正在使用 .NET6,PowerBI embedded 显示在 Razor 视图中。
如果我使用内置的 PowerBI 保存功能,它总是保存到数据集所在的工作区(并且它工作得很好,这让人相信问题不在于正在生成的 EmbedToken,这就是为什么我这里省略了)。
我已经按照以下(基于 official Microsoft documentation)在 Razor 视图中实现了使用 saveAsParameters 中定义的 targetWorkspaceId 将报告保存到定义的工作区的功能。
<script>
var accessToken = '@Model.EmbedToken.Token';
var models = window['powerbi-client'].models;
var config = {
tokenType: models.TokenType.Embed,
accessToken: accessToken,
datasetId: '@Model.DatasetId.ToString()',
embedUrl: 'https://embedded.powerbi.com/ReportEmbed',
permissions: models.Permissions.All,
settings: {
useCustomSaveAsDialog: true
}
};
// Get a reference to the embedded report HTML element
var reportContainer = $('#reportContainer')[0];
// Embed the report and display it within the div container.
let report = powerbi.createReport(reportContainer, config);
report.on("saveAsTriggered", function (event) {
showModal();
});
function showModal() {
$('#savereport').modal('show');
}
function saveAs() {
let saveAsParameters = {
name: $('#ReportName').val(),
targetWorkspaceId: '@Model.WorkspaceId'
}
var result = report.saveAs(saveAsParameters);
}
// add event handler to load existing report afer saving new report
report.on("saved", function (event) {
alert("Report Saved");
window.location.href = "/Reporting/View?Id=" + event.detail.reportObjectId;
});
</script>
从请求中生成的JSON可以看出正在调用目标工作空间
响应是 403 Forbidden
PowerBI Embedded 错误屏幕
有趣的是,如果我尝试保存到数据集所在的工作区,它甚至会失败,这让我很困惑。
如果我从 saveAsParameters 中省略 targetWorkspaceId,它会保存得很好 - 只是不在所需的工作区中!有人有什么想法吗?
感谢 Andrey 为我指点文档。问题是我在 C# SDK 中使用了 GenerateTokenRequest,而我本应使用 GenerateTokenRequestV2。工作代码如下。
public async Task<EmbedConfig> CreateNewReport()
{
try
{
var result = new EmbedConfig { };
var accessToken = await GetPowerBIAccessTokenAsync();
var tokenCredentials = new TokenCredentials(accessToken, "Bearer");
using var client = new PowerBIClient(new Uri(_powerBISettings.ApiUrl), tokenCredentials);
var identities = new List<EffectiveIdentity> { new EffectiveIdentity(username: _tenant.Id.ToString(), roles: new List<string> { "Tenant" }, datasets: new List<string> { _powerBISettings.DatasetId.ToString() }) };
// old method
//var generateTokenRequestParameters = new GenerateTokenRequest(TokenAccessLevel.Create, identities: identites, datasetId: _powerBISettings.DatasetId.ToString(), allowSaveAs: true);
//EmbedToken tokenResponse = await client.Reports.GenerateTokenForCreateInGroupAsync(_tenant.PowerBIWorkspaceId.Value, generateTokenRequestParameters);
var generateTokenRequestParameters = new GenerateTokenRequestV2(datasets: new List<GenerateTokenRequestV2Dataset> { new GenerateTokenRequestV2Dataset(_powerBISettings.DatasetId.ToString()) }, targetWorkspaces: new List<GenerateTokenRequestV2TargetWorkspace> { new GenerateTokenRequestV2TargetWorkspace(_tenant.PowerBIWorkspaceId.Value) }, identities: identities );
EmbedToken tokenResponse = await client.EmbedToken.GenerateTokenAsync(generateTokenRequestParameters);
result.EmbedToken = tokenResponse;
result.DatasetId = _powerBISettings.DatasetId.ToString();
result.WorkspaceId = _tenant.PowerBIWorkspaceId?.ToString() ?? throw new NullReferenceException("No Power BI workspace set");
return result;
}
catch (Exception exception)
{
throw;
}
}
我在 PowerBI embedded 中跨不同工作区保存报表时遇到问题。对于背景:
- 我们正在使用嵌入到 App Owns Data 场景中的 PowerBI
- 我们正在运行 SaaS、多租户单一数据库方法,我们使用 RLS 在 PowerBI 中分离租户数据
- 我们正在使用将在多个工作区之间共享的单一数据集(根据 Microsoft 文档,我相信 V2 工作区支持它)
- 服务主体的范围定义正确,我们购买并配置了专用容量
- 我们正在使用 .NET6,PowerBI embedded 显示在 Razor 视图中。
如果我使用内置的 PowerBI 保存功能,它总是保存到数据集所在的工作区(并且它工作得很好,这让人相信问题不在于正在生成的 EmbedToken,这就是为什么我这里省略了)。
我已经按照以下(基于 official Microsoft documentation)在 Razor 视图中实现了使用 saveAsParameters 中定义的 targetWorkspaceId 将报告保存到定义的工作区的功能。
<script>
var accessToken = '@Model.EmbedToken.Token';
var models = window['powerbi-client'].models;
var config = {
tokenType: models.TokenType.Embed,
accessToken: accessToken,
datasetId: '@Model.DatasetId.ToString()',
embedUrl: 'https://embedded.powerbi.com/ReportEmbed',
permissions: models.Permissions.All,
settings: {
useCustomSaveAsDialog: true
}
};
// Get a reference to the embedded report HTML element
var reportContainer = $('#reportContainer')[0];
// Embed the report and display it within the div container.
let report = powerbi.createReport(reportContainer, config);
report.on("saveAsTriggered", function (event) {
showModal();
});
function showModal() {
$('#savereport').modal('show');
}
function saveAs() {
let saveAsParameters = {
name: $('#ReportName').val(),
targetWorkspaceId: '@Model.WorkspaceId'
}
var result = report.saveAs(saveAsParameters);
}
// add event handler to load existing report afer saving new report
report.on("saved", function (event) {
alert("Report Saved");
window.location.href = "/Reporting/View?Id=" + event.detail.reportObjectId;
});
</script>
从请求中生成的JSON可以看出正在调用目标工作空间
响应是 403 Forbidden
PowerBI Embedded 错误屏幕
有趣的是,如果我尝试保存到数据集所在的工作区,它甚至会失败,这让我很困惑。
如果我从 saveAsParameters 中省略 targetWorkspaceId,它会保存得很好 - 只是不在所需的工作区中!有人有什么想法吗?
感谢 Andrey 为我指点文档。问题是我在 C# SDK 中使用了 GenerateTokenRequest,而我本应使用 GenerateTokenRequestV2。工作代码如下。
public async Task<EmbedConfig> CreateNewReport()
{
try
{
var result = new EmbedConfig { };
var accessToken = await GetPowerBIAccessTokenAsync();
var tokenCredentials = new TokenCredentials(accessToken, "Bearer");
using var client = new PowerBIClient(new Uri(_powerBISettings.ApiUrl), tokenCredentials);
var identities = new List<EffectiveIdentity> { new EffectiveIdentity(username: _tenant.Id.ToString(), roles: new List<string> { "Tenant" }, datasets: new List<string> { _powerBISettings.DatasetId.ToString() }) };
// old method
//var generateTokenRequestParameters = new GenerateTokenRequest(TokenAccessLevel.Create, identities: identites, datasetId: _powerBISettings.DatasetId.ToString(), allowSaveAs: true);
//EmbedToken tokenResponse = await client.Reports.GenerateTokenForCreateInGroupAsync(_tenant.PowerBIWorkspaceId.Value, generateTokenRequestParameters);
var generateTokenRequestParameters = new GenerateTokenRequestV2(datasets: new List<GenerateTokenRequestV2Dataset> { new GenerateTokenRequestV2Dataset(_powerBISettings.DatasetId.ToString()) }, targetWorkspaces: new List<GenerateTokenRequestV2TargetWorkspace> { new GenerateTokenRequestV2TargetWorkspace(_tenant.PowerBIWorkspaceId.Value) }, identities: identities );
EmbedToken tokenResponse = await client.EmbedToken.GenerateTokenAsync(generateTokenRequestParameters);
result.EmbedToken = tokenResponse;
result.DatasetId = _powerBISettings.DatasetId.ToString();
result.WorkspaceId = _tenant.PowerBIWorkspaceId?.ToString() ?? throw new NullReferenceException("No Power BI workspace set");
return result;
}
catch (Exception exception)
{
throw;
}
}