Embedding PowerBI with ASP.NET Core 2 and Angular(2,4,5)
Background
Two Scenarios
1. User Owns Data - where users will be directly registered in PowerBi portal
2. App Owns Data - you have an application which owns the data and you have users to view these reports but they are not registered in PowerBI as direct users - ISV situation
Following steps are focused on scenario 2 which is app own data, but it is not limited to use this information for scenario 1 as well.
[Flow of authentication and authorization (from Microsoft documentation)]
Step 1: Register your app
Make sure your app is registered in Aure portal and enable PowerBI Api for that particular app.
Step 2: Get an access token
https://docs.microsoft.com/en-us/power-bi/developer/embedding-content
The interesting part would be getting an access token using the master account. Microsoft has provided information on how to do this in ASP.Net MVC (refer to below link), but this is just not working as UserPasswordCredential class is not available in .Net Core 2 as it does not support this approach of non-interactive authentication. Well, in this particular scenario we definitely required to authenticate master user account with username and password. In this case, we have to use non-interactive authentication by calling the OAuth Api as follows.
private async Task<OAuthResult> AuthenticateAsync()
{
var oauthEndpoint = new Uri($"https://login.microsoftonline.com/{your org AAD Tenant ot Common}/oauth2/token");
using (var client = new HttpClient())
{
var result = await client.PostAsync(oauthEndpoint, new FormUrlEncodedContent(new[]
{
new KeyValuePair<string,string>("resource", "https://analysis.windows.net/powerbi/api"),
new KeyValuePair<string,string>("client_id", "your application client id"),
new KeyValuePair<string,string>("client_secret", "your application client secret"),
new KeyValuePair<string,string>("grant_type", "password"),
new KeyValuePair<string,string>("username", "powerbi pro user name"),
new KeyValuePair<string,string>("password", "powerbi pro user password"),
new KeyValuePair<string,string>("scope", "openid")
}
));
var content = await result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<OAuthResult>(content);
}
}
public class OAuthResult
{
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("scope")]
public string Scope { get; set; }
[JsonProperty("experies_in")]
public int ExpiresIn { get; set; }
[JsonProperty("ext_experies_in")]
public int ExtExpiresIn { get; set; }
[JsonProperty("experies_on")]
public int ExpiresOn { get; set; }
[JsonProperty("not_before")]
public int NotBefore { get; set; }
[JsonProperty("resource")]
public Uri Resource { get; set; }
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
}
With above code, you will be able to get an access token for the master account, which will be used to generate embedding token in the next step.
Step 3: Get Embed token
https://github.com/Microsoft/PowerBI-CSharp/tree/master/sdk/PowerBI.Api
Since it is not yet supporting .Net Core, you need to download the source and build it as .Net Core library. You may need to tweak things hear and there, but it is not much effort to do this. Once you do that, you can use following code to generate embedded token to be used in your application clientside to render a PowerBi content in your application.
groupId: this is the app workspace ID and can be found when you go to the app workspace in PowerBI Portal.
reportId: his is the report unique ID and can be found when you go to the particular report in PowerBI Portal.
public static EmbeddedReportConfig GenerateReport(string token, string groupId, string reportId, List filters)
{
EmbeddedReportConfig config = null;
var tokenCredentials = new TokenCredentials(token, "Bearer");
// Create a Power BI Client object. It will be used to call Power BI APIs.
using (var client = new PowerBIClient(new Uri("https://api.powerbi.com"),tokenCredentials))
{
Report report = client.Reports.GetReportInGroup(groupId, reportId);
if(report != null)
{
var requestParameters = new GenerateTokenRequest();
requestParameters.AccessLevel = "View";
if (filters != null)
{
requestParameters.Identities = filters;
}
// Generate EmbedToken This function sends the POST message
//with all parameters and returns the token
EmbedToken embedtoken = client.Reports.GenerateTokenInGroupAsync(
groupId,
reportId,
requestParameters).GetAwaiter().GetResult();
config = new EmbeddedReportConfig();
config.EmbedURL = report.EmbedUrl;
config.GroupID = groupId;
config.ReportData = report;
config.ReportID = reportId;
config.Token = embedtoken?.Token;
config.TokenID = embedtoken?.TokenId;
config.Expiration = embedtoken?.Expiration;
}
}
return config;
}
public class EmbeddedReportConfig
{
public string EmbedURL { get; set; }
public string ReportID { get; set; }
public string GroupID { get; set; }
public Report ReportData { get; set; }
public string Token { get; set; }
public string TokenID { get; set; }
public DateTime? Expiration { get; set; }
}
Let's take a scenario where you want to control which user should see which report (any content) and how to apply filters (forcefully filter the data) in a particular report. You can control what user will see when they access the report. As you already have realized that, we only create embed token for the resource that we want to show to the user, but how to control the data in it?
Request parameters (or filters in the above code snippet) are going to rescue you.
How do these filters work?
There is using the RLS (Row-level security) built into the PowerBi. It uses "Role"s to handle this. Once you have roles, you can easily pass these roles (more than one) when you generate the embed token, where it will be embedded into the Embed Token.
When user views the report using embed token, PowerBi will apply roles in the token, so that user will only see filtered data accordingly. You can read following documentation to understand more. Please note that, you have to use PowerBI desktop app to set up these roles.
https://docs.microsoft.com/en-us/power-bi/service-admin-rls
Let's see how to construct these filters.
[Authorize]
[Route("api/Report/EmbedReport")]
[HttpGet(Name = "EmbedReport")]
public EmbeddedReportConfig EmbedReport(string groupid, string reportid)
{
EmbeddedReportConfig report = null;
if( User has access )
{
var proUserToken = AuthenticateAsync().GetAwaiter().GetResult();
List<effectiveidentity> filters = new List<effectiveidentity>();
filters.Add(new EffectiveIdentity
{
Username = "user id or email",
Roles = new List<string> { "Category1Role", "Category2Role" },
Datasets = new List<string> { "data set ID" }
});
report = GenerateReport(proUserToken.AccessToken, groupid, reportid, filters);
}
return report;
}
Here you have control over user, roles and datasets. This is pretty much all you need to control what needs to be shown to user according to access privileges.
Step 4: Render the report in client-side (front-end)
Add PowerBI client package to your project in Angular ("powerbi-client": "^2.4.7"). Then use following code to get it rendered.
// you need : "powerbi-client": "^2.4.7"
import * as pbi from 'powerbi-client';
powerbi: pbi.service.Service;
embedReportConfig = http.get("api/Report/EmbedReport"); call you server to get the embed token
var config:pbi.IEmbedConfiguration = {
type: 'report',
tokenType: pbi.models.TokenType.Embed,
accessToken: "embedded token you generated in your server side :: embedReportConfig.token",
embedUrl: "Report Url :: embedReportConfig.embedURL",
id: "Report ID :: embedReportConfig.reportID",
permissions: pbi.models.Permissions.Read,
pageName: "Whatever your page name",
settings: {
filterPaneEnabled: false, // this will show/hide filter options
navContentPaneEnabled: true
}
};
let reportContainer = <HTMLElement>document.getElementById('powerBIReportContainer');
this.powerbi.embed(reportContainer, config);
<div id="powerBIReportContainer" class="d-block container-fluid m-0 p-0"></div>
Hope this will help to integrate PowerBI to your ASP.Net Core 2 application without any issue.
Can you explain how to print this report in Angular?
ReplyDeletethere one or two errors in your code...
ReplyDeleteThank you so much for exploring the best and right information.
ReplyDeletePowerbi Read Rest
I need to thank you for this very good read and i have bookmarked to check out new things from your post. Thank you very much for sharing such a useful article and will definitely saved and revisit your site.
ReplyDeleteHire Power bi Developer India
Thank you for sharing such a useful article. It will be useful to those who are looking for knowledge. Continue to share your knowledge with others through posts like these, and keep posting on
ReplyDeleteBig Data Solutions
Advanced Data Analytics Services
Data Modernization Solutions
AI & ML Service Provider
Most slicers produce G-code, a regular type of numerical management language understood by most computer-aided fabrication devices . This means that G-code usually needs to be generated by the slicer for particular brands and models of numerically controlled devices. ABS is stronger (it's best toilet cleaner brush what LEGOs are made from), nevertheless it cools at a rate that always causes the underside layers to curve up, deforming the whole print. These are the 3D printing technologies during which you're most likely to take a position.
ReplyDelete