教程:为客户将 Power BI 报表嵌入应用程序
- 版本 :2023.1(当前版本)
教程:为客户将 Power BI 报表嵌入应用程序
在本教程中,你将了解如何将 Power BI 报表嵌入到 .NET 5.0 应用程序,这属于“为客户嵌入内容”(也称为“应用拥有数据”)解决方案的一部分。 在“为客户嵌入内容”解决方案中,应用用户无需登录到 Power BI 或拥有 Power BI 许可证。
在本教程中,你将了解如何嵌入:
Power BI 报表。
在“为客户嵌入内容”应用中。
使用服务主体。
使用 .NET 5.0。
通过
Microsoft.Identity.Web
库(.NET Core 也支持此库)。
备注
本教程中使用的完整解决方案可从 DOTNET5-AppOwnsData-Tutorial GitHub 存储库获取。
先决条件
Power BI Pro 或 Premium Per User (PPU) 许可证
带有报表的 Power BI 工作区
你自己的 Azure Active Directory (Azure AD) 租户
Azure AD 应用
.NET Core 5 模型视图控制器 (MVC) 应用
.NET Core 5 SDK 或更高版本
集成开发环境 (IDE)。 建议使用以下 IDE 之一:
Visual Studio。
Visual Studio Code(具有 C# 扩展)
资源
在本教程中,你使用:
Power BI REST 报表 API,用于嵌入 URL 并检索嵌入令牌。
Microsoft 标识 Web 身份验证库。
Power BI 嵌入式分析客户端 API,用于嵌入报表。
方法
若要在“为客户嵌入内容”解决方案中嵌入 Power BI 内容,请执行以下步骤:
配置 Azure AD 应用和服务主体。
获取嵌入的参数值。
添加所需的 NuGet 包。
启用服务器端身份验证。
构建应用的客户端。
运行应用程序。
步骤 1 - 配置 Azure AD 应用和服务主体
在本教程中,你将使用服务主体向 Azure AD 验证你的 Web 应用。 还需要一个 Azure AD 应用,使其可以生成 Azure AD 令牌。 通过使用 Azure AD 令牌,你的 Web 应用可以调用 Power BI REST API 并嵌入 Power BI 项,例如报表、仪表板和磁贴。
按照服务主体说明创建 Azure AD 应用,使应用服务主体能够使用 Power BI 内容。
步骤 2 - 获取嵌入的参数值
若要嵌入报表,需要以下值:
域
租户 ID
客户端 ID
客户端机密
工作区 ID
报表 ID
域和租户 ID
如果不清楚自己的域或租户 ID,请参阅查找 Microsoft Azure AD 租户 ID 和主域名。
备注
若要为其他租户上的用户(来宾用户)嵌入内容,你需要调整 authorityUri
参数。
客户端 ID
若要获取客户端 ID GUID(也称为“应用程序 ID”),请执行以下步骤:
登录 Microsoft Azure。
搜索“应用程序注册”,然后选择“应用程序注册”链接。
选择用于嵌入 Power BI 内容的 Azure AD 应用。
从“概述”部分,复制“应用程序(客户端) ID”GUID 。
客户端机密
若要获取客户端机密,请执行下列步骤:
登录 Microsoft Azure。
搜索“应用程序注册”,然后选择“应用程序注册”链接。
选择用于嵌入 Power BI 内容的 Azure AD 应用。
在“管理”下选择“证书和密码”。
在“客户端机密”下,选择“新建客户端密钥” 。
在“添加客户端机密”弹出窗口中,提供应用程序机密的说明,选择应用程序机密过期时间,然后选择“添加” 。
从“客户端机密”部分,复制新创建的应用程序机密的“值”列中的字符串 。 客户端机密值为你的客户端 ID。
备注
请确保在第一次出现客户端密码值时复制它。 在你离开此页面后,客户端密码值将会隐藏起来,你将无法检索它。
工作区 ID
若要获取工作区 ID GUID,请执行以下步骤:
登录 Power BI 服务。
打开要嵌入的报表。
复制 URL 中的 GUID。 GUID 是 /groups/ 和 /reports/ 之间的数字 。
备注
若要以编程方式获取工作区 ID,请使用获取组 API。
报表 ID
若要获取报表 ID GUID,请执行以下步骤:
登录 Power BI 服务。
打开要嵌入的报表。
复制 URL 中的 GUID。 GUID 是 /reports/ 和 /ReportSection 之间的数字 。
备注
若要以编程方式获取报表 ID,请使用获取组中的报表 API。
步骤 3 - 添加所需的 NuGet 包
在开始之前,需要将 Microsoft.Identity.Web
和 Microsoft.PowerBI.Api
NuGet 包添加到应用中。
向你的应用添加所需的 NuGet 包:
在 VS Code 中,打开终端并输入以下代码。
在 Visual Studio 中,导航到“工具”>“NuGet 包管理器”>“包管理器控制台”,然后键入以下代码。
PowerShell复制
dotnet add package Microsoft.Identity.Web
dotnet add package Microsoft.Identity.Web.UI
dotnet add package Microsoft.PowerBI.Api
步骤 4 - 启用服务器端身份验证
通过创建或修改下表中的文件,在应用中启用服务器端身份验证。
文件 | 用途 |
---|---|
Startup.cs | 初始化 Microsoft.Identity.Web 身份验证服务 |
appsettings.json | 配置身份验证详细信息 |
PowerBiServiceApi.cs | 获取 Azure AD 令牌和嵌入元数据 |
HomeController.cs | 将嵌入数据作为模型传递到视图 |
配置启动文件以支持 Microsoft.Identity.Web
修改 Startup.cs 中的代码以正确初始化 Microsoft.Identity.Web
提供的身份验证服务。
将以下代码添加到应用的 Startup.cs 文件。
备注
ConfigureServices
中的代码完成了几项重要任务:
对
AddMicrosoftWebAppCallsWebApi
的调用配置 Microsoft 身份验证库,以获取访问令牌(Azure AD 令牌)。对
AddInMemoryTokenCaches
的调用配置一个令牌缓存,Microsoft 身份验证库将使用该缓存在后台缓存访问令牌和刷新令牌。对
services.AddScoped(typeof(PowerBiServiceApi))
的调用将PowerBiServiceApi
类配置为可使用依赖项注入添加到其他类的服务类。
C#复制
using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using Microsoft.AspNetCore.Authentication;using Microsoft.AspNetCore.Authentication.OpenIdConnect;using Microsoft.AspNetCore.Authorization;using Microsoft.Identity.Web;using Microsoft.Identity.Web.UI;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.HttpsPolicy;using Microsoft.AspNetCore.Mvc.Authorization;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;using AppOwnsData.Services;namespace AppOwnsData{ public class Startup
{ public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
services.AddScoped(typeof(PowerBiServiceApi));
services.AddControllersWithViews(options => { var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
services.AddRazorPages()
.AddMicrosoftIdentityUI();
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} else
{
app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You might want to change this for production scenarios. See https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
}
}
创建身份验证详细信息文件
在本教程中,appsettings.json 文件包含敏感信息,例如客户端 ID 和客户端机密。 出于安全考虑,不建议在设置文件中保留此信息。 在应用程序中嵌入时,请考虑使用更安全的工具(如 Azure Key Vault)来保护敏感信息。
在项目中,创建一个新文件并将其命名为 appsettings.json。
然后将以下代码添加到 appsettings.json 中:
JSON复制
{ "AzureAd": { "Instance": "https://login.microsoftonline.com/", "Domain": "yourtenant.onMicrosoft.com", "TenantId": "", "ClientId": "", "ClientSecret": "", "CallbackPath": "/signin-oidc", "SignedOutCallbackPath": "/signout-callback-oidc"
}, "PowerBi": { "ServiceRootUrl": "https://api.powerbi.com/"
}, "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information"
}
},"AllowedHosts": "*"}填写从步骤 2 - 获取嵌入参数值获取的嵌入参数值。
Domain
- 域和租户 IDTenantId
- 域和租户 IDClientId
- 客户端 IDClientSecret
- 客户端机密
备注
在上述代码中,将 PowerBi:ServiceRootUrl
参数作为自定义配置值添加,以跟踪 Power BI 服务的基 URL。 在对 Microsoft 公有云中的 Power BI 服务进行编程时,URL 为 https://api.powerbi.com/
。 但是,Power BI 服务的根 URL 在其他云(例如政府云)中将有所不同。 因此,自定义配置值存储为项目配置值,从而可以根据需要对其进行更改。
获取 Azure AD 访问令牌,并调用 Power BI 服务
为了嵌入 Power BI 内容(如报表和仪表板),应用需要获取 Azure AD 令牌。 若要获取令牌,则需要一个配置对象。
本部分中的代码使用 .NET Core 依赖项注入模式。 当你的类需要使用服务时,你可以为该服务添加构造函数参数。 .NET Core 运行时负责在运行时传递服务实例。 在这种情况下,构造函数使用 IConfiguration
参数注入 .NET Core 配置服务的实例,该参数用于从 appsettings.json 中检索 PowerBi:ServiceRootUrl
配置值。 ITokenAcquisition
参数名为 tokenAcquisition
,它包含对 Microsoft.Identity.Web
库提供的 Microsoft 身份验证服务的引用。 ITokenAcquisition
参数用于从 Azure AD 获取访问令牌。
RequiredScopes
字段包含一个字符串数组,该数组包含由 Power BI 服务 API 支持的一组委托权限。 当应用程序通过网络调用以获取 Azure AD 令牌时,该应用程序将传递这组委托权限,以便 Azure AD 可以将其包含在其返回的访问令牌中。
备注
验证是否已使用 Web 应用所需的范围配置 Azure AD 应用。 有关详细信息,请参阅更改 Azure AD 应用权限。
在应用的项目中,创建名为“服务”的新文件夹。
在“服务”文件夹中,创建名为“PowerBiServiceApi.cs”的新文件 。
将以下代码添加到 PowerBiServiceApi.cs 中。
C#复制
using System;using System.Linq;using System.Threading.Tasks;using Microsoft.Extensions.Configuration;using Microsoft.Identity.Web;using Microsoft.Rest;using Microsoft.PowerBI.Api;using Microsoft.PowerBI.Api.Models;using Newtonsoft.Json;namespace AppOwnsData.Services { // A view model class to pass the data needed to embed a single report
public class EmbeddedReportViewModel { public string Id; public string Name; public string EmbedUrl; public string Token;
} public class PowerBiServiceApi { private ITokenAcquisition tokenAcquisition { get; } private string urlPowerBiServiceApiRoot { get; } public PowerBiServiceApi(IConfiguration configuration, ITokenAcquisition tokenAcquisition) { this.urlPowerBiServiceApiRoot = configuration["PowerBi:ServiceRootUrl"]; this.tokenAcquisition = tokenAcquisition;
} public const string powerbiApiDefaultScope = "https://analysis.windows.net/powerbi/api/.default"; // A method to get the Azure AD token (also known as 'access token')
public string GetAccessToken() { return this.tokenAcquisition.GetAccessTokenForAppAsync(powerbiApiDefaultScope).Result;
} public PowerBIClient GetPowerBiClient() { var tokenCredentials = new TokenCredentials(GetAccessToken(), "Bearer"); return new PowerBIClient(new Uri(urlPowerBiServiceApiRoot), tokenCredentials);
} public async Task GetReport(Guid WorkspaceId, Guid ReportId) {
PowerBIClient pbiClient = GetPowerBiClient(); // Call the Power BI service API to get the embedding data.
var report = await pbiClient.Reports.GetReportInGroupAsync(WorkspaceId, ReportId); // Generate a read-only embed token for the report.
var datasetId = report.DatasetId; var tokenRequest = new GenerateTokenRequest(TokenAccessLevel.View, datasetId); var embedTokenResponse = await pbiClient.Reports.GenerateTokenAsync(WorkspaceId, ReportId, tokenRequest); var embedToken = embedTokenResponse.Token; // Return the report embedded data to caller.
return new EmbeddedReportViewModel {
Id = report.Id.ToString(),
EmbedUrl = report.EmbedUrl,
Name = report.Name,
Token = embedToken
};
}
}
}
修改 HomeController.cs 文件
在此代码示例中,使用依赖项注入来修改 HomeController.cs 文件。 按照上一步操作,通过在 ConfigureServices
方法中调用 services.AddScoped
将 PowerBiServiceApi
类配置为服务。 使用此代码将 PowerBiServiceApi
参数添加到构造函数,.NET Core 运行时将创建一个 PowerBiServiceApi
实例并将其传递给构造函数。
在 Controllers 文件夹中,打开 HomeController.cs 文件,并向其中添加以下代码:
C#复制
using System;using System.Collections.Generic;using System.Diagnostics;using System.Linq;using System.Threading.Tasks;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Mvc;using Microsoft.Extensions.Logging;using AppOwnsData.Models;using AppOwnsData.Services;namespace AppOwnsData.Controllers{
[Authorize] public class HomeController : Controller
{ private PowerBiServiceApi powerBiServiceApi; public HomeController(PowerBiServiceApi powerBiServiceApi)
{ this.powerBiServiceApi = powerBiServiceApi;
}
[AllowAnonymous] public IActionResult Index()
{ return View();
} public async Task Embed() { // Replace these two GUIDs with the workspace ID and report ID you recorded earlier.
Guid workspaceId = new Guid("11111111-1111-1111-1111-111111111111");
Guid reportId = new Guid("22222222-2222-2222-2222-222222222222"); var viewModel = await powerBiServiceApi.GetReport(workspaceId, reportId); return View(viewModel);
}
[AllowAnonymous]
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error()
{ return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
步骤 5 - 构建应用的客户端
对于客户端实现,需要创建或修改下表中列出的文件:
文件 | 用途 |
---|---|
embed.js | 包含客户端 JavaScript 代码 |
Embed.cshtml | 包含应用的文档对象模型 (DOM),以及用于嵌入报表的 DIV |
为嵌入式报表创建容器
在本教程中,创建 Embed.cshtml 文件,该文件包含一个 div
元素(这是嵌入式报表的容器)和三个脚本。
在“视图”/“主页”文件夹中,创建名为 Embed.cshtml 的文件 。
将以下代码添加到 Embed.cshtml 文件。
HTML复制
@model AppOwnsData.Services.EmbeddedReportViewModel;div id="embed-container" style="height:800px;">div>@section Scripts {
script src="https://cdn.jsdelivr.net/npm/powerbi-client@2.18.0/dist/powerbi.min.js">script>
script>
var viewModel = {
reportId: "@Model.Id",
embedUrl: "@Model.EmbedUrl",
token: "@Model.Token"
};
script>
script src="~/js/embed.js">script>}
添加客户端 JavaScript 以嵌入报表
若要嵌入 Power BI 内容,需要创建一个配置对象。 若要详细了解如何创建配置对象,请参阅嵌入报表。
在本教程中,你将创建一个名为 embed.js 的 JavaScript 文件,其中带有一个配置对象,用于嵌入使用 models
变量的报表。
可以使用对 window['powerbi-client'].models
的调用来初始化 models
。 models
变量用于设置配置值,如 models.Permissions.All
、models.TokenType.Aad
和 models.ViewMode.View
。
powerbi.embed
函数使用 models
配置对象嵌入报表。
在“wwwroot”/“js”文件夹中,创建名为 embed.js 的文件 。
将以下代码添加到 embed.js 文件。
Javascript复制
$(function () { // 1 - Get DOM object for the div that's the report container.
var reportContainer = document.getElementById("embed-container"); // 2 - Get the report embedding data from the view model.
var reportId = window.viewModel.reportId; var embedUrl = window.viewModel.embedUrl; var token = window.viewModel.token // 3 - Embed the report by using the Power BI JavaScript API.
var models = window['powerbi-client'].models; var config = { type: 'report', id: reportId, embedUrl: embedUrl, accessToken: token, permissions: models.Permissions.All, tokenType: models.TokenType.Embed, viewMode: models.ViewMode.View, settings: { panes: { filters: { expanded: false, visible: true }, pageNavigation: { visible: false }
}
}
}; // Embed the report and display it within the div container.
var report = powerbi.embed(reportContainer, config); // 4 - Add logic to resize the embed container on a window resize event.
var heightBuffer = 12; var newHeight = $(window).height() - ($("header").height() + heightBuffer);
$("#embed-container").height(newHeight);
$(window).resize(function () { var newHeight = $(window).height() - ($("header").height() + heightBuffer);
$("#embed-container").height(newHeight);
});
});
步骤 6 - 运行应用程序
完成上述所有步骤后,即可运行应用程序。 尝试运行应用程序,并试验 Power BI 报表的嵌入方式。 可以使用 Power BI 嵌入式分析客户端 API 来通过客户端 API 增强你的应用。
重要
如果使用免费嵌入试用令牌进行开发,则必须购买生产容量。 在购买容量之前,“免费试用版”横幅将继续显示在嵌入式报表顶部。
应用准备就绪后,可以将嵌入式应用移动到生产环境。