You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerBIClient调用GenerateToken返回NotFound错误排查求助

Power BI报表嵌入问题解决方案

一、解决"NotFound"错误的核心步骤

1. 修正API调用方法

你当前使用的client.Reports.GenerateToken仅适用于"我的工作区"(My Workspace),指定自定义工作区ID时必须用GenerateTokenInGroup方法。替换报错行代码:

// 替换原报错的GenerateToken调用
var embedTokenResponse = client.Reports.GenerateTokenInGroup(new Guid(workspaceId), new Guid(reportId), embedTokenRequest);

2. 验证ID有效性

确认workspaceId和reportId是完整的36位Guid字符串,无多余空格或格式错误。可直接在Power BI服务中复制:

  • 工作区ID:进入工作区→右上角"设置"→"工作区设置"→复制"工作区ID"
  • 报表ID:打开报表→地址栏中reports/后的字符串即为报表ID

3. 确保服务主体权限

用于生成AccessToken的Azure AD服务主体(对应clientId)必须满足:

  • 已被添加至目标工作区,角色至少为成员(具备生成嵌入令牌的权限)
  • 在Azure AD应用注册中,已添加Power BI API的应用权限(需管理员同意),例如Report.Read.All、Workspace.Read.All

4. 检查AccessToken有效性

用本地JWT解析工具验证获取的AccessToken,确保scp字段包含Report.Read.All等必要权限。

二、无Azure AD登录的嵌入方案适配

针对非域内用户,采用**嵌入令牌(Embed Token)**方案,无需用户登录Azure AD,由Web门户后端统一生成令牌。结合你的ClaimsPrincipal获取用户信息,可实现自定义身份传递(支持行级安全RLS)。

修改后的完整代码示例

public void EmbedReport()
{
    string clientId = "你的客户端ID";
    string clientSecret = "你的客户端密钥";
    string tenantId = "你的租户ID";
    string workspaceId = "目标工作区ID";
    string reportId = "目标报表ID";

    var accessToken = GetAccessToken(clientId, clientSecret, tenantId);
    var tokenCredentials = new TokenCredentials(accessToken);

    using (var client = new PowerBIClient(new Uri("https://api.powerbi.com"), tokenCredentials))
    {
        // 从ClaimsPrincipal获取当前门户用户信息
        var currentUser = System.Web.HttpContext.Current.User as ClaimsPrincipal;
        var userName = currentUser?.FindFirst(ClaimTypes.Name)?.Value;
        var userEmail = currentUser?.FindFirst(ClaimTypes.Email)?.Value;

        // 构建嵌入令牌请求,添加自定义身份信息(用于RLS)
        var embedTokenRequest = new GenerateTokenRequest(TokenAccessLevel.View)
        {
            Identity = new CustomIdentity(userName, new List<string> { userEmail })
        };

        // 使用正确的GenerateTokenInGroup方法
        var embedTokenResponse = client.Reports.GenerateTokenInGroup(new Guid(workspaceId), new Guid(reportId), embedTokenRequest);

        // 将embedTokenResponse.Token传递给前端用于嵌入报表
        // 前端Web Forms页面示例:
        // <div id="reportContainer"></div>
        // <script>
        //   var embedConfiguration = {
        //     type: 'report',
        //     id: '@reportId',
        //     embedUrl: '@(client.Reports.GetReportInGroup(new Guid(workspaceId), new Guid(reportId)).EmbedUrl)',
        //     accessToken: '@embedTokenResponse.Token',
        //     settings: { panes: { filters: { visible: false } } }
        //   };
        //   var report = powerbi.embed(document.getElementById('reportContainer'), embedConfiguration);
        // </script>
    }
}

private string GetAccessToken(string clientId, string clientSecret, string tenantId)
{
    var authority = $"https://login.microsoftonline.com/{tenantId}";
    var confidentialClientApplication = ConfidentialClientApplicationBuilder
        .Create(clientId)
        .WithClientSecret(clientSecret)
        .WithAuthority(new Uri(authority))
        .Build();

    var scopes = new[] { "https://analysis.windows.net/powerbi/api/.default" };
    // 替换.Result为.GetAwaiter().GetResult(),避免Web Forms异步死锁
    var result = confidentialClientApplication.AcquireTokenForClient(scopes).ExecuteAsync().GetAwaiter().GetResult();

    return result.AccessToken;
}

关键适配点

  • 从ClaimsPrincipal提取用户信息,通过CustomIdentity传递到嵌入令牌,报表可基于这些信息配置行级安全
  • 前端使用Power BI JavaScript SDK,直接用后端生成的嵌入令牌和报表EmbedUrl完成嵌入
  • 优化异步调用方式,避免Web Forms环境下的死锁问题

内容的提问来源于stack exchange,提问作者inosu812

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 02:44:58