Project Westminster - Windows 10 "Hosted Web App"

Project Westminster

Auf der Fachkonferenz Build Ende April in San Francisco hat Microsoft vier Universal Windows Platform Bridges vorgestellt, eine davon ist Project Westminster. Diese hat zwar nichts mit dem Stadtteil im Herzen Londons zu tun, ist aber ebenfalls eine Reise Wert.

Überblick über Universal Windows Bridges

Mobile Strategie

Viele Unternehmen wählen heutzutage als mobile Strategie einen "Mobile Web"-Ansatz. Die Vorteile eines solchen liegen auf der Hand: dazu gehören u.a. die Unabhängigkeit von Stores, leichtere und schnellere Update-Möglichkeiten uvm. Mit Windows 10, der Universal Windows Platform und den dazughörigen Universal Windows Platform Bridges bietet Microsoft nun eine Möglichkeit, das für Unternehmen mit einem "Mobile Web"-Ansatz mit Sicherheit interessant ist.: Project Westminster.

Project Westminster ist die der erste der vier Uninversal Windows Platform Bridges: Im Prinzip geht es darum, eine mobile Internetseite als "App Container" bereitzustellen und die Logik der App der Internetseite zu überlassen. Das Channel9-Video "Creating Hosted Web Apps" veranschaulicht ganz gut, was ich damit meine.

Los gehts ...

Ein Trip nach London will geplant sein und so auch die Reise zu Projekt Westminster. Was benötige ich alles, um loszulegen?

Entwicklungsumgebung

Zunächst benötige ich einen Rechner mit Windows 10 und dem aktuellen Windows 10 SDK. Mehr Informationen dazu findet man auf der Seite dev.windows.com.
Und passend dazu, muss auch die aktuelle Version von Visual Studio 2015 installiert sein.

Projekt Setup

Hier werden im ersten Schritt zwei Projekte angelegt, eines für die mobile Webseite und eines für die Windows 10 App. Die App kann dabei in einer beliebigen Sprache, wie HTML5 und JavaScript, geschrieben sein, oder wie in meinem Fall mit C# und auf Basis von .NET. Für die Webanwendung lege ich eine ASP.NET MVC-Seite an – aber auch hier hätte man die freie Wahl. Außerdem habe ich entschieden, dass meine „unglaubliche“ App auf GitHub zu Hause sein wird: Deshalb hier schon mal der Link für den Quellcode – Github Repro Westminster.

Und nun zu den ersten Schritten, zu Beginn lege ich ein neues Projekt an:
File -> New Project -> Web -> ASP.net Webapplication Dialog

Nachdem Visual Studio die Webanwendung angelegt hat, starte ich diese mit F5 und stelle fest, dass die Anwendung zwar mit Internet Explorer, Chrome und Firefox läuft, aber der neue Browser Microsoft Edge nicht darauf zugreifen kann.

Lokale Seite kann von Microsoft Edge nicht angezeigt werden.

Workaround Lokale Seite mit Edge anzeigen

Microsoft Edge ist eine Universal Windows Platfrom App und unterliegt dementsprechend dem Security-Modell der Universal Windows Platfrom und das besagt, dass diese Apps nicht lokal kommunizieren dürfen – von dem Fiddler-Workaround abgesehen. Da wir die Anwendung in einer Modern Web App hosten wollen und die neue Webview zufällig die Edge Engine ist, sollten wir unsere Web App entsprechend gleich mit Microsoft Edge testen. Dazu kann folgendes PowerShell-Script genutzt werden, welches Edge den lokalen Zugriff auf "LocalHost" erlaubt:

PS: CheckNetIsolation LoopbackExempt -a -n=Microsoft.MicrosoftEdge_8wekyb3d8bbwe
Windows 10 Build 10158 und höher. Stand 13/7/2015 Applies to Build: 10158, 10159, 10162, 10167, 10240

Powershell erkennt die Parameter nicht?

Sollte, aus welchen Gründen auch immer, PowerShell die Argumente nicht erkennen, gibt es einen kleinen Trick: Einfach Anführungszeichen an das Microsoft Edge-Paket hängen.

PS: CheckNetIsolation LoopbackExempt -a -n="Microsoft.MicrosoftEdge_8wekyb3d8bbwe"
Windows 10 Build 10158 und höher. Stand 13/7/2015 Applies to Build: 10158, 10159, 10162, 10167, 10240

Powershell Script to activate Localhost debugging with Microsoft Edge

Nachdem "OK" von PowerShell gehe ich erneut auf die lokale Seite und siehe da, sie wird korrekt angezeigt.

Achtung! Leider ist dieses Script an den Paket-Namen gebunden, von daher ist es wahrscheinlich eine gute Idee, das Edge-Paket mit der richtigen Versionsnummer und Paketnummer zu nehmen. So habe ich heraus gefunden, wie das MS Edge-Paket heißt: MSDN Powershell Script to retrieve Store Apps

Unsere Seite funktioniert nun schon mal. Schritt 2 ist das Hinzufügen einer passenden Windows 10 App – also erzeuge ich auch diese. Wie bereits erwähnt, nehme ich die C#- und .NET-Variante.

Im Solution Explorer - Rechtsclick auf die Solution -> Add -> New Project

Im "New Project"-Dialog wähle ich eine neue Windows Universal App aus und füge diese der Solution hinzu.

Um das Projekt-Setup zu komplettieren, muss der App noch mitgeteilt werden, dass sie ein Container für eine mobile Internet-Seite ist.

Setup der Container App für die Mobile Web App

Das Ganze klingt komplizierter als es ist, im Solution Explorer suche ich als Erstes nach der Datei "Package.appxmanifest".

Anschließend suche ich im XML Schema den Eintrag Application. STRG + F -> Suche in der Datei Package.appxmanifest nach dem Begriff Application

In diesem Abschnitt muss nun ein Eintrag hinzugefügt werden:
Regel für das Laden von Webcontent.

<uap:ApplicationContentUriRules> <uap:Rule Type="include" WindowsRuntimeAccess="all" Match="http://lockscreen.azurewebsites.net/" /> </uap:ApplicationContentUriRules>

Sicherheitsmodell von Windows Universal Apps

Beim Sicherheitsmodell von Universal Windows Apps gilt es, unterschiedliche Dinge zu beachten: Jede Universal Windows App unterliegt dem Sicherheitsmodel der Windows Runtime. Die Details hierzu findet man unter MSDN. Es wird genau definiert, was eine Anwendung alles darf oder nicht darf. Über Capabilities kann sich eine Anwendung zusätzliche Berechtigungen für z.B. die Interaktion mit Webcam und weiterer Hardware über die Runtime und am Ende des Tages dem Benutzer selbst holen. Benutzer können Anwendungen auch jeder Zeit die Berechtigung auf einzelne APIs wieder entziehen. Eine Liste der Capabilities findet man unter: Windows Dev Center - Capabilities.

Sicherheitsmodel von Web Apps im Kontext einer Anwendung.

In unserem Fall wollen wir er Web App aber die Möglichkeit geben, auf Windows Runtime-Funktionalitäten zuzugreifen, also der Webseite ermöglichen, im Kontext einer App zu laufen. Dazu gibt es folgende Möglichkeiten:

  • "none" blockiert den kompletten Zugriff auf die Windows Runtime APIs – das ist der Standardwert.
  • "AllowForWebOnly" erlaubt einem Remote-Script auf der Webseite den Zugriff auf die lokalen Windows Runtime-Komponenten, die im App Package inkludiert sind.
  • "all" erlaubt den kompletten Zugriff auf Windows Runtime Namespaces und lokale Komponenten, die im App Package inkludiert sind.

Bei unserem Beispiel soll die Anwendung die Erlaubnis bekommen, auf den kompletten Namespace der Windows Runtime zuzugreifen. Mehr Informationen zum Thema "Hosted Web Apps" und den Sicherheitsregeln bekommen Interessierte im Windows Dev Center.

Ein weiterer wichtiger Punkt ist der Endpoint, unter dem die "Hosted Web App" zur Verfügung stehen soll. Obwohl das Internet groß ist, habe ich mich dafür entschieden, die Anwendung auf Azure zu hosten, weil Azure Web Apps einfach unschlagbar einfach im Deployment sind.

Das Deployment der Web App

Ich habe bereits einen Deployment Stamp für die Webseite auf Microsoft Azure angelegt und stelle die Seite nun via Visual Studio bereit.

Im Solution Explorer: Rechtsklick auf das Webprojekt -> Publish

Es erscheint der Publishing-Dialog: Ich wähle eine bereits angelegte Web App-Instanz aus.

Achtung: Ich habe die Web App auf .NET 4.5.2 gestellt und da wir keine Datenbank benötigen auch den Connection String für DB leer gelassen. Anschießend bestätige das gGnze via Publish und schon ist unsere Web App im Netz.

Ich bestätige das ganze via Publish und schon ist unsere Web App im Internet.

Wem das jetzt zu schnell ging und wer mehr über Azure Web Apps erfahren möchte, dem empfehle ich den TechTalk.Cloud Microsoft Azure Web Apps sowie die Azure Online Dokumentation zum Thema Deployment.

Da wir jetzt auch auf unseren Endpunkt eine Webseite haben, das kann in Ihrem Fall aber auch der Endpunkt "http://lockscreen.azurewebsites.net/" oder jede andere beliebige Webseite sein, wird es zeit, sich um den App Container zu kümmern.

Hosted Web App

Im nächsten Schritt wechseln wir zurück zu unserer Universal Windows App. In der mainpage.xaml fügen wir ein Webview-Control hinzu.

Zeigt die Dokumentenstruktur und den XAML Code unserer "Hosted Web App"

So weit so unspektakulär – da unsere "Hosted Web App" responsiv sein soll und den Inhalt unserer mobilen Webseite anzeigen soll, reagieren wir auf den Event Window.SizeChanged.
Dazu implementiere ich die beiden Methoden OnNavigateFrom und OnNavigateTo, welche Einstiegspunkt und Endpunkt der Navigation sind. Das Code Behind File in C# für die Mainpage.xaml sieht dann wie folgt aus.

Das war es auch schon, was unsere App können muss. Natürlich kann man die Anwendung mit vielen weiteren Funktionen anreichern. Aber jetzt zurück zu unserer Web App – so sieht unsere Windows 10 "Hosted Web App" bis jetzt aus.

So sieht unsere Windows 10 "Hosted Web App" bis jetzt aus.

Aufruf von Windows Runtime APIs durch Hosted Web App

Jetzt kommen wir zu den eigentlich richtig „coolen“ Dingen bei "Hosted Web Apps" für Windows 10. Über JavaScript lässt sich auf die Windows Runtime zugreifen. Dazu wechsle ich in die Web App und passe die index.cshtml unter Views - Home an.

Index.cshtml Struktur

Die index.cshtml gibt uns ein wenig Auskunft darüber, welche Szenarien wir hier erreichen wollen. Das erste Szenario soll sich um das Setzten eines Hintergrundbildes kümmern. In der Datei finden wir unterschiedlichsten „Werbekram“ im Header, weshalb ich dieses Div einfach mal ausgeblendet habe. Das row-Div ist schon interessanter. Hier finden wir die beiden Szenarien, im ersten Fall haben wir einen Button der Open File heißt und id="action" trägt. Im darauf Folgendem finden wir das JavaScript zum Button "Open File".

Was wir hier sehen können, ist das ein JavaScript Event Listener wartet, ob jemand auf den Button drückt. Ist das der Fall, rufen wir eine Function auf und überprüfen ob wir im Kontext einer App oder im Kontext eines Browsers sind. Sind wir im Kontext eines Browsers, so teilen wir dem User über eine MessageBox mit: "it is the web, what did you expect?". Sollten wir aber im Kontext einer App laufen – das Ganze wird über folgenden code validiert

if (window.Windows)

– dann öffnen wir den File Picker im Thumbnail Mode und setzen ihn an den Pfad der Bilder des Benutzers. Den Dateifilter passen wir dementsprechend auf Bilddateiformate an. Im nächsten Schritt warten wir, bis der Benutzer ein Bild ausgewählt hat. Hat der Benutzer ein Bild gewählt, so setzen wir dieses als Hintergrundbild des Login Screens. Wenn nicht brechen wir einfach ab.

Das ist auch schon die ganze Magie hinter dem ersten Code-Snippet, lassen wir das ganze im Kontext des Browsers laufen, bekommen wir die erwartete Fehlermeldung.

Unter Windows 10 sieht das Resultat dann so aus:

Und tatsächlich lässt sich damit das Hintergrundbild des Lockscreens in Windows ändern. Das ist schon ziemlich cool! Dariusz hat ein Video zum ersten Szenario gemacht und man kann sich das Ganze auf Vimeo anschauen.

Im zweiten Szenario wollen wir auf die Hardware des Gerätes zugreifen, genauer gesagt auf die "Camera Capture UI". Die Frage ist, wie komme ich an die entsprechende API? Die Kollegen von Windows 10 haben eine Art Snippet Library gebaut – man findet sie unter: http://rjs.azurewebsites.net/.

Suche nach Camera Capture UI

Das Ergebnis meiner Suche ist ein Snippet, das ich jetzt in mein bestehendes JavaScript integriere.

Die fertige Index.cshtml findet man auf Github und so sieht unsere finale App dann aus:

Fertig?

Na ja, fast! Wie gesagt ist unsere mobile Webseite fast fertig. Im Kontext von Edge und anderen modernen Browsern ist es keine schlechte Idee die Kompatibilität der Seite zu testen. Auf der Internetseite modern.ie finden wir ein Static Site Scan Tool. Die dort enthaltenen Tests stehen auch auf modern.ie finden wir einen Static Site Scan Tool. Die dort enthaltenen Tests stehen auch auf Microsoft Edge Tools - Github zur Verfügung. Dadurch lassen sich die Tests ins eigene Unit Testing oder Acceptance Testing einbinden. Und man kann einen ersten Eindruck erhalten ob die Website für Westminster geeignet ist. Grundsätzlich ist es wichtig, dass die Seite über ein Responsive Design verfügt und sich an HTML5 und CSS3 orientiert.

Zusammenfassung

Windows 10 bietet nicht nur die Möglichkeit, Webseiten in einen App Container zu packen, sondern erlaubt es dem Entwickler auch, von Mobile Web Apps auf die Windows Runtime APIs zuzugreifen. Und das ganze auf einen, wie ich finde, guten Weg. Es wird nicht überprüft, ob wir uns im Kontext eines bestimmten Browsers befinden, sondern ob wir direkt auf Windows geladen wurden. Noch einen Schritt weitergedacht könnte man auch die zur Verfügung stehenden Möglichkeiten abfragen. Und je nach dem, ob ein Gerät diese Möglichkeiten unterstützt, kann unsere Web App diese verwenden oder eben nicht. Offen bleiben nach diesen Blogpost noch die Fragen nach der On-/Offline-Fähigkeit sowie nach einer Liste der Features und Funktionen.

Aber wäre dem nicht so, hätte ich ja nichts mehr zu schreiben. ;)

P.S.: Mein Kollege Kiril Seksenov hat ebenfalls dieses Thema beleuchtet.