Sunday, February 4, 2024
0 comments

PowerBI Embedded Report Integration with Web Application in ASP.NET Core using Azure Service Principal Method(Part-2)

1:51 PM

 


Assalamulaikum,

This is the continuation of this post where I discussed about cloud configuration of Embedding report. Today I will discuss about programming part for asp.net core:

Configuring ASP.NET Core application

Application must know few settings to show report from Power BI. Add the following JSON to your appsettings.json file and fill in appropriate values.

"PowerBI": {
  "ApplicationId": "****fca1230-3d9a-4a31-de94-d0***",
  "ApplicationSecret": "****uHlkX1LXHQ194/EaH6crrrSo****",
  "ReportId": "****-471e-19***",
  "WorkspaceId": "***9c1-4e2d-b550-****",
  "AuthorityUrl": "https://login.windows.net/common/oauth2/authorize/",
  "ResourceUrl": "https://analysis.windows.net/powerbi/api",
  "ApiUrl": "https://api.powerbi.com/",
  "EmbedUrlBase": "https://app.powerbi.com/",
  "UserName": "gunnar@example.com",
  "Password": "****"
}

* please replace * sign with real data

To have these settings as object we need class for Power BI settings block.

public class PowerBISettings
{
    public Guid ApplicationId { get; set; }
    public string ApplicationSecret { get; set; }
    public Guid ReportId { get; set; }
    public Guid? WorkspaceId { get; set; }
    public string AuthorityUrl { get; set; }
    public string ResourceUrl { get; set; }
    public string ApiUrl { get; set; }
    public string EmbedUrlBase { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
}


To make settings available in ASP.NET Core application we load settings when application starts and register them as singleton in framework-level dependency injection. This is done in ConfigureServices() method of Startup class.


var powerBISettings = Configuration.GetSection("PowerBI").Get<PowerBISettings>();
services.AddSingleton(powerBISettings);

We need also some NuGet packages:

  • Microsoft.IdentityModel.Clients.ActiveDirectory
  • Microsoft.PowerBI.Api

And Power BI JavaScript library:

From Power BI JavaScript library take minified version from dist folder and copy it to scripts folder of your web application.

Now we have basic work done and it’s time to get to real business.


Getting access token

.NET Core libraries for Azure AD doesn’t support username and password authentication like it was before. Instead we have to write our own hack to get access token for username and password authentication.

Add the following method to controller that hosts action for report.

private async Task<string> GetPowerBIAccessToken(PowerBISettings powerBISettings)
{
    using(var client = new HttpClient())
    {
        var form = new Dictionary<string, string>();
        form["grant_type"] = "password";
        form["resource"] = powerBISettings.ResourceUrl;
        form["username"] = powerBISettings.UserName;
        form["password"] = powerBISettings.Password;
        form["client_id"] = powerBISettings.ApplicationId.ToString();
        form["client_secret"] = powerBISettings.ApplicationSecret;
        form["scope"] = "openid";

        client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");

        using (var formContent = new FormUrlEncodedContent(form))
        using (var response = await client.PostAsync(powerBISettings.AuthorityUrl, formContent))
        {
            var body = await response.Content.ReadAsStringAsync();
            var jsonBody = JObject.Parse(body);
           
            var errorToken = jsonBody.SelectToken("error");
            if(errorToken != null)
            {
                throw new Exception(errorToken.Value<string>());
            }

            return jsonBody.SelectToken("access_token").Value<string>();
        }
    }
}

Now it’s time to display report.

Displaying report

Here’s the code for controller action to display Power BI report. Notice how I use controller action injection to get Power BI settings to method.

public async Task<IActionResult> Report([FromServices]PowerBISettings powerBISettings)
{
    var result = new PowerBIEmbedConfig { Username = powerBISettings.UserName };
    var accessToken = await GetPowerBIAccessToken(powerBISettings);
    var tokenCredentials = new TokenCredentials(accessToken, "Bearer");

    using (var client = new PowerBIClient(new Uri(powerBISettings.ApiUrl), tokenCredentials))
    {
        var workspaceId = powerBISettings.WorkspaceId.ToString();
        var reportId = powerBISettings.ReportId.ToString();
        var report = await client.Reports.GetReportInGroupAsync(workspaceId, reportId);
        var generateTokenRequestParameters = new GenerateTokenRequest(accessLevel: "view");
        var tokenResponse = await client.Reports.GenerateTokenAsync(workspaceId, reportId, generateTokenRequestParameters);

        result.EmbedToken = tokenResponse;
        result.EmbedUrl = report.EmbedUrl;
        result.Id = report.Id;
    }

    return View(result);
}

Here is my view to show the report.

@model PowerBIEmbedConfig
<style>
   
#reportContainer {
       
height: 600px;
       
width: 100%;
       
max-width: 2000px;
    }
</style>
<script src="https://npmcdn.com/es6-promise@3.2.1"></script>
<script src="~/js/powerbi.min.js"></script>

<div id="reportContainer"></div>

@section scripts {
   
<script>
   
// Read embed application token from Model
   
var accessToken = "@Model.EmbedToken.Token";

   
// Read embed URL from Model
   
var embedUrl = "@Html.Raw(Model.EmbedUrl)";

   
// Read report Id from Model
   
var embedReportId = "@Model.Id";

   
// Get models. models contains enums that can be used.
   
var models = window['powerbi-client'].models;

   
// Embed configuration used to describe the what and how to embed.
   
// This object is used when calling powerbi.embed.
   
// This also includes settings and options such as filters.
   
// You can find more information at https://github.com/Microsoft/PowerBI-JavaScript/wiki/Embed-Configuration-Details.
   
var config = {
        type:
'report',
        tokenType: models.TokenType.Embed,
        accessToken: accessToken,
        embedUrl: embedUrl,
        id: embedReportId,
        permissions: models.Permissions.All,
        settings: {
            filterPaneEnabled:
true,
            navContentPaneEnabled:
true
        }
    };

    $(document).ready(
function () {
       
// Get a reference to the embedded report HTML element
       
var reportContainer = $('#reportContainer')[0];

       
// Embed the report and display it within the div container.
        powerbi.embed(
reportContainer, config);
    });
   
</script>
}

And here is my Power BI embedded report when I run my ASP.NET Core application.


Sample Report:




Thank you




0 comments:

 
Toggle Footer