教學課程:為客戶在應用程式中內嵌Power BI報表

在本教學課程中,您會瞭解如何在 .NET 5.0 應用程式中內嵌 Power BI 報表,作為內嵌客戶(也稱為 app-owns-data) 解決方案的一部分。 在內嵌客戶解決方案中,您的應用程式使用者不需要登入 Power BI 或擁有 Power BI 授權。

在本教學課程中,您將瞭解如何內嵌:

  • Power BI 報表。
  • 在 embed-for-your-customers 應用程式中。
  • 使用 服務主體
  • 使用 .NET 5.0。
  • 使用連結 Microsoft.Identity.Web 庫 (.NET Core 也支援此連結庫)。

注意

本教學課程中使用的完整解決方案可從 DOTNET5-AppOwnsData-Tutorial GitHub 存放庫取得。

必要條件

資源

在本教學課程中,您會使用:

方法

若要在內嵌客戶解決方案中內嵌 Power BI 內容,請遵循下列步驟:

  1. 設定您的 Microsoft Entra 應用程式和服務主體

  2. 取得內嵌參數值

  3. 新增必要的 NuGet 套件

  4. 啟用伺服器端驗證

  5. 建置應用程式的用戶端

  6. 執行您的應用程式

步驟 1 - 設定您的 Microsoft Entra 應用程式和服務主體

在本教學課程中,您會使用服務主體,針對 Microsoft Entra ID 驗證 Web 應用程式。 您也需要 Microsoft Entra 應用程式,以便產生 Microsoft Entra 令牌。 透過使用 Microsoft Entra 令牌,您的 Web 應用程式可以呼叫 Power BI REST API 並內嵌 Power BI 專案,例如報表、儀錶板和磚。

請遵循服務主體指示來建立 Microsoft Entra 應用程式,並讓應用程式的服務主體與您的 Power BI 內容搭配使用。

步驟 2 - 取得內嵌參數值

若要內嵌報表,您需要下列值:

網域和租用戶標識碼

如果您不知道網域或租使用者標識符,請參閱 尋找 Microsoft Entra 租使用者標識碼和主要功能變數名稱

注意

若要 在不同的租使用者(來賓使用者)上內嵌使用者的內容,您需要調整 authorityUri 參數。

Client ID

若要取得用戶端識別碼 GUID (也稱為 應用程式識別碼),請遵循下列步驟:

  1. 登入 Microsoft Azure

  2. 搜尋 應用程式註冊,然後選取 應用程式註冊 連結。

  3. 選取您用來內嵌 Power BI 內容的 Microsoft Entra 應用程式。

  4. 從 [概觀]段中,複製應用程式 (用戶端) 識別元 GUID。

用戶端密碼

若要取得客戶端密碼,請遵循下列步驟:

  1. 登入 Microsoft Azure

  2. 搜尋 應用程式註冊,然後選取 應用程式註冊 連結。

  3. 選取您用來內嵌 Power BI 內容的 Microsoft Entra 應用程式。

  4. 在 [管理] 下,選取 [憑證與秘密]。

  5. 在 [用戶端祕密] 下,選取 [新增用戶端祕密]

  6. 在 [ 新增客戶端密碼 ] 彈出視窗中,提供應用程式秘密的描述、選取應用程式秘密到期的時間,然後選取 [ 新增]。

  7. 從 [客戶端密碼] 區段中,複製新建立之應用程式秘密之 [值] 資料行中的字串。 用戶端密碼值是用戶端 識別碼

注意

請務必在客戶端密碼值第一次出現時複製它。 離開此頁面之後,客戶端密碼將會隱藏,您將無法擷取其值。

工作區識別碼

若要取得工作區標識碼 GUID,請遵循下列步驟:

  1. 登入 Power BI 服務。

  2. 開啟您想要內嵌的報表。

  3. 從 URL 複製 GUID。 GUID 是 /groups//reports/之間的數位。

    A screenshot showing workspace ID GUID in the Power B I service U R L

注意

若要以程序設計方式取得工作區標識符,請使用 取得群組 API。

報表標識碼

若要取得報表標識元 GUID,請遵循下列步驟:

  1. 登入 Power BI 服務。

  2. 開啟您想要內嵌的報表。

  3. 從 URL 複製 GUID。 GUID 是 /reports//ReportSection 之間的數位。

    A screenshot showing report ID GUID in the Power B I service U R L

注意

若要以程式設計方式取得報表標識碼,請使用 取得群組 API 中的報表。

步驟 3 - 新增必要的 NuGet 套件

開始之前,您必須將 、 和 Microsoft.PowerBI.Api NuGet 套件新增Microsoft.Identity.Web至您的應用程式。

將必要的 NuGet 套件新增至您的應用程式:

  • VS Code 中,開啟終端機並輸入下列程式代碼。

  • Visual Studio 中,流覽至 [工具>NuGet 封裝管理員> 封裝管理員 控制台],然後輸入下列程序代碼。

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 取得 Microsoft Entra 令牌和內嵌元數據
HomeController.cs 將內嵌數據當做模型傳遞至檢視

設定您的啟動檔案以支援 Microsoft.Identity.Web

修改 Startup.cs 中的程式碼,以正確初始化 所提供的Microsoft.Identity.Web驗證服務。

將下列程式代碼新增至應用程式的 Startup.cs 檔案。

注意

中的 ConfigureServices 程式代碼會完成數個重要事項:

  1. 的呼叫會設定 AddMicrosoftWebAppCallsWebApi Microsoft 驗證連結庫以取得存取令牌(Microsoft Entra 令牌)。
  2. 呼叫 可設定 AddInMemoryTokenCaches Microsoft 驗證連結庫用來在幕後快取存取令牌和重新整理令牌的令牌快取。
  3. 呼叫 services.AddScoped(typeof(PowerBiServiceApi)) 會將 類別設定 PowerBiServiceApi 為服務類別,這個類別可以使用相依性插入新增至其他類別。
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 檔案包含敏感性資訊,例如 用戶端標識碼客戶端密碼。 基於安全性考慮,我們不建議您將此資訊保留在配置檔中。 在應用程式中內嵌時,請考慮更安全的工具,例如 Azure 金鑰保存庫,以保護敏感性資訊。

  1. 在您的專案中,建立新的檔案,並將它命名為 appsettings.json

  2. 將下列程式代碼新增至 appsettings.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": "*"
    }
    
  3. 填入從 步驟 2 - 取得內嵌參數值

注意

在上述程式代碼中,PowerBi:ServiceRootUrl參數會新增為自定義組態值,以追蹤 Power BI 服務 的基底 URL。 當您在 Microsoft 公用雲端中針對 Power BI 服務 進行程式設計時,URL 為 https://api.powerbi.com/。 不過,Power BI 服務 的根 URL 在其他雲端中不同,例如政府雲端。 因此,自定義組態值會儲存為項目組態值,因此您可以視需要加以變更。

取得 Microsoft Entra 存取令牌,並呼叫 Power BI 服務

若要內嵌Power BI內容,例如報表和儀錶板,您的應用程式必須取得 Microsoft Entra 令牌。 若要取得令牌,您需要設定 物件

本節中的程序代碼會使用 .NET Core 相依性插入模式。 當您的類別需要使用服務時,您可以新增該服務的建構函式參數。 .NET Core 運行時間會負責在運行時間傳遞服務實例。 在此情況下,建構函式會使用 IConfiguration 參數插入 .NET Core 組態服務的實例,以用來從 appsettings.json 擷取PowerBi:ServiceRootUrl組態值。 名為 ITokenAcquisition 的參數 tokenAcquisition會保存連結庫所 Microsoft.Identity.Web 提供之 Microsoft 驗證服務的參考。 參數 ITokenAcquisition 是用來從 Microsoft Entra ID 取得存取令牌。

欄位RequiredScopes會保存字串數位,其中包含 Power BI 服務 API 支援的一組委派許可權。 當您的應用程式透過網路呼叫以取得 Microsoft Entra 令牌時,它會傳遞這組委派的許可權,讓 Microsoft Entra ID 可以將它們包含在它傳回的存取令牌中。

注意

確認您的 Microsoft Entra 應用程式 已設定 Web 應用程式所需的範圍。 如需詳細資訊,請參閱 變更 Microsoft Entra 應用程式的許可權

  1. 在應用程式的專案中,建立標題為 Services 的新資料夾。

  2. 在 [ 服務 ] 資料夾中,建立標題為 PowerBiServiceApi.cs 的新檔案。

  3. 將下列程式代碼新增至 PowerBiServiceApi.cs

    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<EmbeddedReportViewModel> 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 檔案,並將下列程式代碼新增至其中:

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<IActionResult> 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 內嵌報表容器的專案,以及三個腳本。

  1. 在 [檢視/首頁] 資料夾中,建立名為Embed.cshtml的檔案。

  2. 將下列程式代碼新增至 Embed.cshtml 檔案。

    @model AppOwnsData.Services.EmbeddedReportViewModel;
    
    <div id="embed-container" style="height:800px;"></div>
    
    @section Scripts {
    
        <!-- powerbi.min.js is the JavaScript file that loads the client-side Power BI JavaScript API library.
        Make sure that you're working with the latest library version.
        You can check the latest library available in https://cdnjs.com/libraries/powerbi-client -->
        <script src="https://cdn.jsdelivr.net/npm/powerbi-client@2.18.0/dist/powerbi.min.js"></script>
    
        <!-- This script creates a JavaScript object named viewModel which is accessible to the JavaScript code in embed.js. -->
        <script> 
            var viewModel = {
                reportId: "@Model.Id",
                embedUrl: "@Model.EmbedUrl",
                token: "@Model.Token"
            }; 
        </script>
    
        <!-- This script specifies the location of the embed.js file -->
        <script src="~/js/embed.js"></script>
    }
    

新增用戶端 JavaScript 以內嵌報表

若要內嵌 Power BI 內容,您必須建立組態物件。 若要深入瞭解如何建立組態物件,請參閱 內嵌報表

在本教學課程中,您會使用組態物件建立名為 embed.js 的 JavaScript 檔案,以內嵌使用 變數 models的報表。

您可以使用 對 window['powerbi-client'].models的呼叫來初始化models。 變數 models 是用來設定組態值,例如 models.Permissions.Allmodels.TokenType.Aadmodels.ViewMode.View

powerbi.embed 式會使用組 models 態物件來內嵌報表。

  1. wwwroot/js 資料夾中,建立名為 embed.js 的檔案。

  2. 將下列程式代碼新增至 embed.js 檔案。

    $(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 來增強您的應用程式。

重要

如果您使用免費內嵌試用令牌進行開發,則必須購買生產容量。 在購買容量之前, 免費試用版 橫幅會繼續出現在內嵌報表的頂端。

當您的應用程式準備就緒時,您可以將 內嵌應用程式移至生產環境