Ich selbst bin ja begeisterter Power BI Anwender, bzw. Entwickler. Microsoft hat hier ein Tool entwickelt, welches ungeahnte Möglichkeiten im Reporting bietet. Da sind eigene Chart-Typen, die man mittels Typescript erstellen kann, schon ein faszinierendes Feature, aber das heutige Thema ist nicht minder interessant: Das Hosten ganzer Power BI Berichte, oder einzelner Charts in einer eigenen Applikation. Ein brandneues Feature, welches auf der Build-Konferenz 2016 frei gegeben wurde. Schließlich und endlich (kann) das dann so aussehen, wie in folgendem Bild – man beachte die eigene URL:
Schritte, um Power BI einzubinden
Für die ungeduldigen unter euch, hier gibt es ein komplettes Beispiel auf github:
https://github.com/Microsoft/PowerBI-CSharp/tree/master/samples/webforms/
Im Großen und Ganzen sind folgende Schritte auszuführen:
- Es wird ein Power BI Account benötigt
- Im Power BI Web Portal muß zumindest:
- Ein Dashboard mit einem Tile hinterlegt sein, wenn man nur ein Tile einbinden möchte
- Ein Report hinterlegt sein, wenn man den gesamten Bericht einbinden möchte
- Ein Azure Active Directory (Azure AD) authentication token muss erzeugt warden, dafür muss die eigene App zuvor registriert werden.
- Abfragen der benötigten Informationen zum Einbinden eines:
- Tile - Dashboard ID und Tile ID
- Report - Report ID und die embed URL
- Das eigentliche Einbinden:
- Für ein Tile, wird ein click event handler benötigt, der zum Power BI dashboard navigiert.
- Um den Report einzubinden, wird das SRC Attribut eines IFrame zur embed Url gesetzt.
Beispiel einer Integration
Zuerst benötigt man natürlich einen Power BI Zugang, diesen bekommt man hier: https://powerbi.microsoft.com, nach erfolgter Anmeldung landet man in Power BI selbst und zwar in der Web-Variante, nämlich hier: https://app.powerbi.com
Authentication Token
Zuerst muss die eigene Applikation hier registriert werden, entweder hier https://dev.powerbi.com/apps, oder im Azure Management Portal hier: https://manage.windowsazure.com/
Ich habe meine Anwendung im Azure Management Portal registriert, dazu ist folgendes anzuwählen: Active Directory (links im Baum) -> Anwendungen -> Hinzufügen -> Eine von meinem Unternehmen entwickelte Anwendung hinzufügen. Es erscheint ein Dialog, wo man einen beliebeigen Namen eingibt, im zweiten Schritt eine beliebeige Umleitungs-URL ( beispielsweise https://login.live.com/oauth20_desktop.srf). Danach hat man eine eigne Client ID (für Desktop Applikationen), bzw. noch zusätzlich ein Client Secret (für Web Applikationen). Allerdings muss noch die Berechtigung für das Power BI Service hinzugefügt werden.
Jetzt sollte der Zugriff mit ein paar Zeilen Code auch schon funktionieren, dazu aber etwas später genaueres.
Ein Beispielbericht in Power BI
Sobald man seinen eigenen Power BI Account sein eigen nennt, kann man bereits loslegen und sich entweder einen eigenen Report bauen, oder einen der Beispielberichte übernehmen, das geht am einfachsten mit dem Button links unten und dem nachfolgenden Link , das erste davon „Procurement Analysis Sample“ bietet sich direkt an es gleich in seine eigene Berichtsbibliothek zu übernehmen.
Somit ist der erste Schritt getan, ein Beispieldashboard befindet sich in unserer Power BI Bibliothek.
Benötigte Informationen zum Einbinden
Power BI stellt eine REST API zur Verfügung, mit Hilfe derer es möglich ist, an all die Informationen hernazukommen, die man benötigt, um einen Report einzubinden. Die gesamte Dokumentation der API gibt es hier: http://docs.powerbi.apiary.io und glücklicherweise kann man dort auch gleich die API calls testen. Dazu muss man sich mit seinem eigenen Power BI Account anmelden, da alle Aufrufe auf den eigenen Account abzielen, schließlich möchte man ja auch genau diese Informationen haben.
Zuerst braucht man die Liste aller DashBoards - nach dem vorigen Schritt sollte ja zumindest eines in der eigenen Power BI Bibliothek vorhanden sein – diese erhält man mittels:
GET: https://api.powerbi.com/beta/myorg/dashboards
Da wir jetzt noch keinen eigenen Client haben, lässt sich das am einfachsten hier ausführen:
http://docs.powerbi.apiary.io/#reference/dashboards-preview/dashboards-collection/list-all-dashboards
Der „Try“ Button wechselt zur Consolen-Ansicht und der „Call Resource“ Button und dieser setzt den API Call ab, das Resultat ist ein JSON-String mit der Auflistung aller DashBoards im eigenen Account.
{
"@odata.context": "http://wabi-north-europe-redirect.analysis.windows.net/beta/myorg/$metadata#dashboards",
"value": [
{
"id": "cf235bc3-2e3e-40e9-b193-4c4f57a54928",
"displayName": "Procurement Analysis Sample",
"isReadOnly": false
}
]
}
Die Liste der eigenen Reports erhält man hier:
http://docs.powerbi.apiary.io/#reference/report-preview/reports-collection/list-all-reports
Das Ergebnis zeigt die ID und die embedUrl der Berichte (in diesem Fall des Procurement Analysis Sample Berichts).
{
"@odata.context": "http://wabi-north-europe-redirect.analysis.windows.net/beta/myorg/$metadata#reports",
"value": [
{
"id": "5e58ab10-0b77-4d56-bfcd-4d2001b7d733",
"name": "Procurement Analysis Sample",
"webUrl": "https://app.powerbi.com/reports/5e58ab10-0b77-4d56-bfcd-4d2001b7d733",
"embedUrl": "https://app.powerbi.com/reportEmbed?reportId=5e58ab10-0b77-4d56-bfcd-4d2001b7d733"
}
]
}
Damit hat man schon alles zusammen, um einen eigenen Bericht darzustellen.
WCF Beispiel mit Selfhosting
Abschließend möchte ich einen etwas anderen Anwendungsfall zeigen, nämlich ein WCF Service, welches einen PowerBI Report zurückliefert. Im Großen und Ganzen ist das in einem WCF-Client mit ein paar Zeilen C#-Code erledigt:
· Hinzufügen der ADAL Library zur Authentifizierung:
Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory
· HTML-Seite mit Iframe und URL für den Report
· JavaScript, um den Access-Token „unterzujubeln“
[ServiceContract]
public interface IHtmlService
{
[OperationContract]
[WebGet] //System.ServiceModel.Web
Stream GetSampleReport();
}
public class HtmlService : IHtmlService
{
public static string Token;
public Stream GetSampleReport()
{
var reportUrl = "<your_embedUrl>";
string script = "<script>function postActionLoadReport() {" +
"var m = { action: 'loadReport', accessToken: '" + Token + "' };" +
"message = JSON.stringify(m);" +
"iframe = document.getElementById('iFrameEmbedReport');" +
"iframe.contentWindow.postMessage(message, '*');" +
"}</script>";
string html = "<html><head> " + script + "</head><body><iframe id='iFrameEmbedReport' onload ='postActionLoadReport()' src ='" + reportUrl + "' height = '768px' width = '1024px' frameborder = '1' seamless ></ iframe ></body></html>";
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
return new MemoryStream(Encoding.UTF8.GetBytes(html));
}
}
Jetzt stellt sich die Frage, woher denn der Access-Token kommt. Hier gibt es nun mehrere Möglichkeiten, da wäre zuerst einmal das Snippet, wo der bekannte Web-Dialog hochpoppt, wo der Anwender Username und Passwort eingibt – die ClientID kommt aus der Azure Konfiguration für die eigene Applikation, genauso wie die redirectUri:
private static string clientID = "<your_clientID>";
private static string redirectUri = "https://login.live.com/oauth20_desktop.srf";
private static string resourceUri = "https://analysis.windows.net/powerbi/api";
private static string authority = "https://login.windows.net/common/oauth2/authorize";
AuthenticationContext authContext = new AuthenticationContext(authority);
var authResult = authContext.AcquireToken(
resourceUri, clientID, new Uri(redirectUri));
return authResult.AccessToken;
Besser wäre möglicherweise die „Silent“-Variante, also ohne dem Dialog, dazu sind die letzten Zeilen durch folgenden Code auszutauschen – wobei user und password zwei Strings mit den benötigten Informationen ist:
UserCredential uc = new UserCredential(user, password);
var authResult = await authContext.AcquireTokenAsync(resourceUri, clientID, uc);
if (authResult != null && !string.IsNullOrWhiteSpace(authResult.AccessToken))
{
Properties.Settings.Default.AccessToken = authResult.AccessToken;
Properties.Settings.Default.RefreshToken = authResult.RefreshToken;
Properties.Settings.Default.Save();
return authResult.AccessToken;
}
Das Ganze noch als SelfHosting Consolen-Applikation zum Testen:
HtmlService.Token = token.AccessToken;
string baseAddress = "http://localhost:8000/report";
_host = new ServiceHost(typeof(HtmlService), new Uri(baseAddress));
_host.AddServiceEndpoint(typeof(IHtmlService), new WebHttpBinding(), "")
.Behaviors.Add(new WebHttpBehavior());
_host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
Voila, das war es auch schon, somit kann mit dem Browser auch schon zu der gewählten baseAddress navigiert werden und der PowerBI Bericht ist in seiner ganzen Schönheit zu bewundern.
Darstellung in WPF
Soll der Bericht in einem WPF-Client mit dem Webbrowser Control dargestellt werden, dann klappt das auch, man muss allerdings noch den Registry-Key für die Browser Kompatibilität der eigenen Applikation höher setzen:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION
Neuer Key (DWORD):
<name der applikation>.exe und Dezimal 11000 (IE11), bzw. 11001 (IE11, ohne !DOCTYPE)
<name der applikation>.vshost.exe und Dezimal 11001, bzw. 11001
War das erfolgreich, so wird der Bericht auch im Browser Control dargestellt.
Damit ergeben sich tolle Möglichkeiten. Power BI kann somit überall integriert werden, auch in eigenen Applikationen!