Continuous Delivery mit dem Visual Studio Mobile Center

Das neue Visual Studio Mobile Center soll Mobile App Entwicklern den ganzen Continuous Delivery-Ablauf – von Erstellung bis zur Verteilung der App – nun völlig in der Cloud unter einem Dach anbieten. Obwohl es sich noch in der Entwicklung befindet, haben wir es mit unserer ShowTime Xamarin.Forms App auf die Probe gestellt.

Continuous Delivery ermöglicht durch den Einsatz geeigneter Tools, Software in kürzeren Zyklen auszuliefern. Der Fokus liegt hierbei auf der Verwendung automatisierter Verfahren und Werkzeuge, die sicherstellen, dass Software ständig erstellt, getestet und an den Endbenutzer ausgeliefert wird. In Kombination mit dem zugehörigen Benutzerfeedback führt dies zur kontinuierlichen Verbesserung der Softwarequalität.

Bei der Entwicklung von mobilen Apps kommt hinzu, dass deren Lauffähigkeit auf unterschiedlichen Plattformen und einer Vielzahl verschiedener mobiler Endgeräte sichergestellt werden muss. Die Anschaffung einer entsprechenden Anzahl mobiler Testgeräte ist wenig zweckmäßig und zudem teuer. Stattdessen macht man sich besser einen Cloud-Service zunutze, der UI-Tests der mobilen App transparent und vollautomatisch auf entsprechenden Zielgeräten ausführt und die Ergebnisse gesammelt ausgibt. Zusätzlich wären noch App-Nutzungsstatistiken nützlich (z. B. Crash Reports, Performancemetriken, usw.). Genau hier kommt Visual Studio Mobile Center (VSMC) ins Spiel.

Microsoft möchte diese Funktionen künftig konsolidiert unter einem Dach anbieten. Die sich dahinter verbergenden Dienste Xamarin Test Cloud und HockeyApp (modifiziert) werden aber weiterhin auch separat angeboten. Eine Neuheit ist die Möglichkeit, mobile Apps komplett in der Cloud zu erstellen, was die Entwicklung für iOS erleichtert, denn man muss hierfür nicht mehr notgedrungen einen Mac besitzen oder auf Dienste von Drittanbietern wie z. B. MacinCloud zurückgreifen.

Da VSMC sich noch in der Preview-Phase befindet, stellt sich die Frage, ob es neben Beispielanwendungen auch mit einer etwas umfangreicheren Anwendung zurechtkommt. Für diesen Zweck habe ich unsere auf Xamarin.Forms basierende Zeiterfassungs-Showcase-App „ShowTime“ (Plattformen iOS, Android und Windows 10) für Continuous Delivery fit gemacht und den Mobile Center Continuous Delivery-Workflow durchlaufen lassen: Erstellung der App Packages, Ausführen von UI Tests und Verteilung an Stakeholder. Bei dieser Gelegenheit wurde ebenso der Dienst zur Erhebung von Nutzungsstatistiken – Analytics – getestet. Man bemerke, dass für die Xamarin-Plattform die Ausführung von Unit-Tests in diesem Workflow derzeit noch nicht unterstützt wird. Die Umsetzung dieser fehlenden Funktionalität wurde mir in Korrespondenz mit dem VSMC Entwicklungsteam allerdings schon bestätigt.

Des Weiteren hat das VSMC noch zwei Funktionen – Tables und Identity. Mithilfe der Tables kann man ad-hoc Datentabellen erstellen, die per REST-Calls (GET, POST, PATCH, DELETE) ansprechbar sind. Identity ermöglicht es, Benutzerauthentifizierung in seiner App umzusetzen, ohne das Backend ändern zu müssen. Die Authentifizierung erfolgt dabei über einen der folgenden Identity Provider: Azure Active Directory, Facebook, Google, Microsoft Account oder Twitter. Diese zwei Funktionen und die anderen unterstützten Plattformen – Objective-C / Swift, Java und React Native – wurden im Rahmen meiner Evaluierung nicht berücksichtigt. Nebenbei sei erwähnt, dass sich generell alle Features auch über eine öffentliche REST-API ansprechen lassen.

Bereits zu Beginn der Evaluierung fand ich heraus, dass die Unterstützung für UWP in VSMC noch fehlt, weswegen der Workflow nur für die Plattformen Android und iOS getestet werden konnte. Die UWP-Unterstützung ist aber laut VSMC-Roadmap [1] bereits auf der Agenda. Eine weitere Einschränkung sind die für die Anbindung verfügbaren Quellcode-Repositories. Derzeit unterstützt das Mobile Center nämlich nur GitHub-Repositories. Da wir unsere App bisher in einem Visual Studio Team Services (VSTS) Repository hosten, mussten wir also für diesen Zweck zunächst temporär nach GitHub migrieren. Die Unterstützung für VSTS und Bitbucket wurde von Microsoft aber für die Zukunft angekündigt [1].

Hinzufügen einer App

Nachdem man sich erfolgreich am Mobile Center angemeldet hat, muss man zuerst seine mobile App hinzufügen. In diesem Kontext stellt eine App lediglich eine Art Container mit DevOps-Einstellungen einer Anwendung dar, in welchem noch keine Verbindung zum konkreten Code-Repository besteht. Für jede Plattform derselben Anwendung muss jeweils eine separate App hinzugefügt werden. Abbildung 1 veranschaulicht das Hinzufügen des iOS-Clients der ShowTime-App.

Abbildung 1 – Hinzufügen einer neuen App

Builddefinition

Das Erstellen einer App ist für beide Plattformen sehr intuitiv und einfach. Als erstes muss man dem VSMC mitteilen, wo sich der zugehörige Code befindet. Aus der angezeigten Liste der GitHub-Repositories wählt man einfach das jeweilige Repository aus, woraufhin die Verbindung zu diesem hergestellt wird. Danach selektiert man den zu erstellenden Branch (hier: „master“) und bekommt den Dialog aus der Abbildung 2 angezeigt. In diesem Schritt lässt sich die automatische, durch Einchecken startende Erstellung (Build) des Codes einstellen und die Empfängergruppe auswählen, die nach erfolgreicher Erstellung per E-Mail benachrichtigt werden soll. Die Benachrichtigung enthält dann den Download-Link für das Installationspaket der App auf der jeweiligen Plattform. Die Benutzeroberfläche bietet auch die Möglichkeit, die Erstellung manuell zu starten. Weitere Dateien, die während des Build-Vorgangs erzeugt wurden, dies umfasst z. B. auch Build-Logs, können separat heruntergeladen werden.

Es sei bemerkt, dass die ausgewählte Gruppe die App nach jeder erfolgreichen Erstellung ungeachtet der Testergebnisse erhält, sofern die automatische Verteilung aktiv ist. Einer anderen Gruppe, die beispielsweise nur bestimmte Versionen erhalten soll, kann man die App manuell im Schritt „Distribute“ schicken.

Abbildung 2 – Builddefinition für iOS

UI-Tests

Um die App auf mobilen Geräten zu testen, muss man in VSMC einen Testlauf erstellen. Bei der Erstellung wählt man die Geräte, auf denen man seine App testen möchte, und eines der folgenden, derzeit unterstützten Testframeworks aus:

  • Appium
  • Calabash
  • Espresso
  • Xamarin.UITest

Da in unserer ShowTime-App nur Xamarin.UITest zum Einsatz kommt, wurden die anderen Frameworks zunächst nicht getestet.

Man kann ebenfalls die Sprachumgebung des Geräts einstellen und den Testlauf einer sogenannten Testserie zuweisen, die eine Gruppe zusammenhängender Tests darstellt.

Abbildung 3 – Erstellung eines neuen Testlaufs

Wenn man die UI Tests eingestellt hat, bekommt man im letzten Schritt die Anweisungen, wie diese letztlich gestartet werden. Für einen vollständigen Continuous Delivery-Ablauf hätte ich erwartet, dass die UI Tests nach erfolgreichem Build automatisch ausgeführt werden, was allerdings derzeit noch nicht der Fall ist. Die Cloud UI-Tests müssen stattdessen Stand heute jedes Mal manuell gestartet werden – entweder per Kommandozeile oder durch einen REST API-Aufruf. Des Weiteren haben die Tests ausschließlich formalen Charakter und keinerlei Einfluss auf den eigentlichen Continuous Delivery-Prozess. Man erhält als Entwickler lediglich Einsicht in die Testergebnisse. Das Entwicklungsteam hat mir jedoch im Chat bestätigt, dass die UI-Tests in der Zukunft Teil des automatisierten Continuous Delivery-Workflows sein würden: Sie würden nach dem Build-Vorgang automatisch gestartet und nur bei einem positiven Testergebnis würde dann die automatische Verteilung erfolgen.

Abbildung 4 – Testergebnisse eines Testlaufs

Verteilung

Hier werden die Zielgruppen verwaltet, die im „Build“-Teil bei der Einrichtung der automatischen Verteilung der App erscheinen und auswählbar sind. Wie bereits erwähnt, bekommen diese Gruppen bei der Verteilung einen Link zur Installationsdatei per E-Mail zugeschickt. Die Oberfläche bietet ebenfalls die Möglichkeit, die Verteilung an ausgewählte Gruppen durch manuelles Hochladen einer APK-Datei für Android oder einer IPA-Datei für iOS auszulösen. Somit kann man beispielsweise eine Gruppe einrichten, die die App automatisch nach jedem Build bekommen soll (Entwickler, technische Tester, usw.), und eine weitere, die von der automatischen Verteilung ausgeschlossen ist (z. B. fachliche Tester).

Abbildung 5 – Verteilung der Anwendung

Analytics und Crash Reports

Um die Erhebung von Nutzungsstatistiken zu ermöglichen, müssen lediglich zwei Mobile Center-Bibliotheken als Abhängigkeit zu einigen Projekten der App-Solution hinzugefügt und ein paar Initialisierungsaufrufe mit einer für jede Mobile Center App eindeutigen ID eingebaut werden. Danach sendet jede Instanz der Anwendung Daten an das Mobile Center, die man dann in Form diverser Statistiken auf einem Dashboard angezeigt bekommt – Anzahl der aktiven Nutzer, meistverwendete mobile Geräte, usw.

Mithilfe dieser Bibliotheken konnte ich in unserer ShowTime-App auch Aufrufe einbauen, die die Ausführungsdauer bestimmter Aktionen messen, z. B. den Backend-Aufruf beim Einloggen.

Abbildung 6 – Diverse Nutzungsstatistiken

Fazit

Visual Studio Mobile Center hat mich aufgrund der sehr intuitiven Benutzeroberfläche beeindruckt. Als sehr nützlich hat sich der Build in der Cloud erwiesen, denn dadurch braucht man für iOS-Builds nicht zwingend einen Mac oder muss externe Clouddienste nutzen (MacinCloud). Ich konnte Code-Änderungen vornehmen, die iOS-Version der App in der Cloud erstellen lassen und anschließend mithilfe der Cloud-UI-Tests einfach sicherstellen, dass sie auch weiterhin funktioniert. Obwohl der komplette Continuous Delivery-Prozess derzeit nur bedingt unterstützt wird, z. B. weil UI-Tests noch nicht automatisch gestartet werden können, hat man am Ende die Erstellung, UI Tests und Verteilung unter einem Dach, was sehr praktisch ist. Microsofts Entwicklungsteam ist sehr agil, gibt gerne Hilfestellung und antwortet auf Chat-Nachrichten meist innerhalb eines Werktages. Über die Preise gibt es noch keine Auskünfte seitens Microsoft; während der Testphase ist die Nutzung dagegen kostenlos.

Referenzen

[1] https://docs.microsoft.com/en-us/mobile-center/general/roadmap

[2] https://docs.microsoft.com/en-us/mobile-center/

[3] https://www.visualstudio.com/de/vs/visual-studio-mobile-center/

[4] https://mobile.azure.com/

OAuth 2.0 & Basic Authentication in derselben Web API

In einer ASP.NET Web API 2-Anwendung standen wir vor dem Problem pro Operation jeweils eine von zwei alternativen Authentifizierungsmethoden zu unterstützen: die Azure Active Directory-Bearer-Authentifizierung (OAuth 2.0) und Basic Authentication. Der naheliegende Ansatz, die Azure AD-Authentifizierung durch die OWIN-Middleware [1] [2] und die Basic Authentication als Web API-Authentifizierungsfilter [3] zu implementieren funktioniert jedoch nicht. Aus diesem Grund habe ich nach einer anderen Lösung suchen müssen.

Einstellung der Authentifizierung

Zur Authentifizierung am Azure AD wurde eine Implementierung aus der Microsoft.Owin.Security.ActiveDirectory-Assembly verwendet, die in der Startup.Auth-Datei wie folgt konfiguriert wurde:

   1: public void ConfigureAuth(IAppBuilder app)

   2: {

   3:     app.UseWindowsAzureActiveDirectoryBearerAuthentication(

   4:         new WindowsAzureActiveDirectoryBearerAuthenticationOptions

   5:         {

   6:             AuthenticationType = AuthenticationTypes.AzureActiveDirectory,

   7:             Tenant = ...,

   8:             TokenValidationParameters = new TokenValidationParameters

   9:             {

  10:                 ...

  11:             }

  12:         }

  13:     );

  14: }

Für die Basic Authentication wurde unsere eigene Implementierung verwendet, die als ein IAuthenticationFilter-Attribut [3] realisiert wurde („ConfiguredBasicAuthenticationAttribute“).

Einsatz im Controller

In folgendem Controller musste die GET-Methode Azure AD-Authentication und die POST-Methode Basic Authentication verwenden:

   1: [Authorize]

   2: public class UsersController : ApiController

   3: {

   4:     // Soll nur Bearer Authentication verwenden

   5:     public async Task Get()

   6:     {

   7:         ...

   8:     }

   9:

  10:     // Soll nur Basic Authentication verwenden

  11:     [OverrideAuthentication]

  12:     [ConfiguredBasicAuthentication(...)]

  13:     public async Task Post(...)

  14:     {

  15:         ...

  16:     }

  17: }

Das Authorize-Attribut ohne Angabe von Benutzernamen oder -Rollen tut nichts weiter als allen nichtauthentifizierten Benutzern den Zugriff auf den ganzen Controller zu verweigern. Da die Azure AD Authentication im Rahmen der OWIN-Middleware bereits global registriert wurde, war der ursprüngliche Gedanke diese direkt bei der POST-Methode durch die Basic Authentication zu ersetzen.

Um dies zu verwirklichen war die Azure AD Authentication zu überbrücken, um anschließend unsere ConfiguredBasicAuthentication zu erzwingen. Der OverrideAuthentication-Filter [4], wie der Name sagt, sollte für die Überbrückung aller bisher registrierten Authentifizierungsmethoden sorgen, um den Einsatz des ConfiguredBasicAuthentication-Authentifizierungsattributs zu ermöglichen.,

Dieser Controller hat jedoch die gewünschte Funktionalität nicht aufgewiesen. Die POST-Methode hat nämlich trotz der Angabe des OverrideAuthentication-Attributs beide Authentifizierungsmethoden zugelassen, als würde die Überbrückung überhaupt nicht funktionieren.

Warum es nicht funktioniert

Warum dieser Ansatz nicht funktioniert hat, wird einem klar, wenn man unter die Haube schaut, wie eine HTTP-Anfrage im Zusammenhang mit Authentifizierung und Autorisierung verarbeitet wird. Um über den Zugang eines Benutzers auf eine geschützte Ressource eine Entscheidung treffen zu können, sind im Regelfall folgende zwei Schritte erforderlich:

  1. Authentifizierung: Feststellung der Identität des Benutzers. (“Wer ist dieser Benutzer?”)
  2. Autorisierung: Ermittlung der Zugangsrechte des authentifizierten Benutzers (“Darf er das machen?”)

In unserer Anwendung hat die Authentifizierung an zwei verschiedenen Stellen stattgefunden:

  1. Azure AD-Authentifizierung in der Host-Schicht im Rahmen der Katana-Middleware (Microsofts Implementierung von OWIN). Diese erfolgt beim Eingang von HTTP-Anfragen und ist unabhängig von der Web API-Schicht.
  2. Basic Authentication in der Web API-Schicht als Authentication Filter.

Diesen Ablauf veranschaulicht folgende Abbildung:

Abbildung 2

Abbildung 1 – Die von uns verwendeten Teile der Web API 2-Pipeline

Das Override-Attribut hat nicht den durch die Azure AD-Authentifizierung bereits gesetzten Principal überschrieben, weil es nur Authentifizierungsfilter aus der Web API-Schicht außer Kraft setzen kann. Falls eine HTTP-Anfrage Azure AD-Authentifizierung verwendet hat, wurde der Principal von der Katana-Middleware vor der Verarbeitung in der Web API-Schicht gesetzt. Wenn keine Basic Authentication in der Anfrage vorhanden war, hat der Web API-Filter lediglich keinen Principal gesetzt und der bereits Vorhandene ist unberührt geblieben. Demzufolge war der Benutzer authentifiziert und der Authorization Filter hat ihn einfach durchgelassen.

Lösung

Da der Geltungsbereich des Override-Attributs nur auf die Web API-Schicht beschränkt ist, wäre eine der vorstellbaren Lösungen, die Azure AD-Authentifizierung irgendwie in die Web API-Schicht zu verlagern. Im Web API 2 lässt sich dies durchaus machen und zwar, indem man die automatisch erfolgende Host-Authentifizierung ausschaltet und auf die bereits registrierte Azure AD-Authentifizierung von einem Authentication Filter aus (Web API-Schicht) verweist. Auf diese Weise bleibt die Authentifizierung in der Katana-Middleware weiterhin bestehen mit dem Unterschied, dass sich die Katana-Authentifizierung nun wie ein Web API-Authentifizierungsfilter verhält.

Folgender Codeschnipsel aus der Register-Methode aus der WebApiConfig-Datei registriert die Azure AD-Authentifizierung global als ein Web API-Authentifizierungsfilter, welcher jetzt vom Override-Attribut wie gewünscht außer Kraft gesetzt werden kann.

   1: config.SuppressDefaultHostAuthentication();

   2: config.Filters.Add(

   3:        new HostAuthenticationFilter(AuthenticationTypes.AzureActiveDirectory)

   4: );

Die HostAuthenticationFilter-Klasse ist ein Authentifizierungsfilter aus der Web API 2-Pipeline, der im Konstruktor als Parameter die bei der Katana-Middleware registrierte Authentifizierungsmethode entgegennimmt und bei Anfrage aufruft. In unserem Fall wird dieser Filter – da global registriert – immer aufgerufen, es sei denn, er wurde vom Override-Attribut überbrückt. Da dieser nun überbrückbar gemacht wurde, werden in der genannten POST-Methode keine Benutzer mehr durchgelassen, die durch Basic Authentication nicht identifiziert wurden.

Referenzen

[1] https://azure.microsoft.com/de-de/documentation/articles/active-directory-authentication-scenarios/

[2] https://azure.microsoft.com/de-de/documentation/articles/active-directory-devquickstarts-webapi-dotnet/

[3] https://msdn.microsoft.com/en-us/library/system.web.http.filters.iauthenticationfilter(v=vs.118).aspx

[4] https://msdn.microsoft.com/en-us/library/system.web.http.overrideauthenticationattribute(v=vs.118).aspx

ASP.NET Core 1.0 – ein Portierungsversuch

Das sich derzeit in Entwicklung befindliche ASP.NET Core 1.0 soll auch auf Linux und OS X laufen können. Wir wollten es wissen und haben deshalb einen Portierungsversuch unserer bestehenden Web API nach ASP.NET unternommen.

Vorgehensweise
Die Portierung war in zwei Schritten angedacht: Zunächst Umstellung nach ASP.NET Core 1.0, danach Portierung nach .NET Core 1.0. Da ASP.NET Core auch auf dem vollständigen .NET Framework laufen kann, wollte ich zunächst einmal die ganze API auf ASP.NET Core umstellen, bevor ich es dann mit dem neuen .NET Core aufnehme. Denn bei beiden Schritten erwartete ich Kompatibilitätsprobleme.

Da nur bestimmte Teile des bestehenden .NET Frameworks nach .NET Core portiert wurden, bestand in unserem Fall die Gefahr, dass auch Teile unserer API aus Inkompatibilitätsgründen nicht nach .NET Core portiert werden können. Des Weiteren werden von uns derzeit auch externe Programmbibliotheken, z. B. für die Kommunikation mit CRM, verwendet, die womöglich ebenfalls nicht unter .NET Core lauffähig sind.

In der Visual Studio-Solution unserer API befinden sich zwei Projekttypen – Web API-Projekte und Klassenbibliotheken. Der Ansatz, zunächst eine neue Solution zu erstellen, um anschließend die bestehenden Class Libraries einfach zu referenzieren, stand uns nicht zur Verfügung, da für ASP.NET Core eine komplett neue Vorlage für Klassenbibliotheksprojekte verwendet werden muss. In diesen Projekten kann man dann nämlich die zu unterstützenden Frameworks einstellen (.NET Core oder .NET Framework) und somit theoretisch für alle Plattformen gleichzeitig entwickeln.

Demzufolge musste ich also eine neue Solution erstellen und alle vorhandenen Dateien manuell in die jeweiligen Projekttypen kopieren. Aus oben genannten Gründen wurde für’s Erste völlig auf .NET Core verzichtet, in der Hoffnung, nach der Portierung nach ASP.NET Core auch diese letzte Hürde nehmen zu können. Die Portierung der Klassenbibliotheken verlief ohne größere Probleme: Es war allerdings gelegentlich erforderlich, eine höhere Version der bisher verwendeten Komponenten des .NET Frameworks zu verwenden.

Probleme
ASP.NET Core 1.0 hat seinen eigenen Dependency Injection Container mit derzeit minimaler Funktionalität. Unsere API verwendete bislang Unity für DI; dieser lässt sich zurzeit aber nicht ohne Weiteres einbinden, denn eine offizielle Unterstützung gibt es noch nicht, wenngleich im Internet diverse Personen bereits Einbindungsversuche unternommen haben [2] [3]. Diese sind allerdings mittlerweile veraltet und ein Umstieg auf den mitgelieferten DI-Container war deshalb erforderlich.

Hier konnte ich allerdings bisher keine Möglichkeit finden, die bereits registrierten Interfaces manuell aufzulösen. Anscheinend kann man mit diesem bis jetzt nur Services registrieren, die anschließend bei Bedarf vom ASP.NET Core 1.0 aufgelöst werden.

In einem unserer Projekte verwenden wir auch zwei Bibliotheken für die Kommunikation mit Microsoft Dynamics CRM („Microsoft.Xrm.Client“ und „Microsoft.Xrm.Sdk“). Nach der Übernahme dieser DLLs aus der alten Solution konnten deren Versionen nicht richtig erkannt werden, weswegen neuere Versionen zunächst per NuGet heruntergeladen wurden.

Als schwierigstes Problem hat sich die Portierung der Authentifizierung erwiesen. Unsere API verwendet nämlich ein JWT-Token für die Authentifizierung der Nutzer. Für dessen Verwendung unter ASP.NET Core gibt es eine Unmenge von Beispielen [4] [5], allerdings mittlerweile gänzlich veraltet und teilweise nicht einmal mehr kompilierbar. Am Ende war es mir gelungen herauszufinden, wie man JwtBearerMiddleware im neuen ASP.NET registriert, woraufhin ich allerdings auf neue Probleme gestoßen bin. Die InMemorySymmetricSecurityKey-Klasse, die in unserem Projekt für die Einstellung der TokenValidationParameters verwendet wird, war in der neuesten Version des System.IdentityModel.Tokens-NuGet-Pakets nicht vorhanden.

Im Laufe der Portierung waren bereits einige Kompromisse gemacht worden und bei diesem Problem hat sich Scott Hanselmans Aussage über ASP.NET Core 1.0 bestätigt: ASP.NET 4.6 ist die ausgereiftere Plattform und dies sollte bei der Wahl des zu verwendenden ASP.NET-Frameworks bedacht werden [1]. Mangels Dokumentation und aufgrund veralteter Code-Beispiele wurde letzten Endes die Portierung gestoppt. Denn selbst wenn sie mit großer Mühe erfolgreich gewesen wäre, hätte das Endprodukt aufgrund der schnellen Veränderung von ASP.NET Core 1.0 womöglich bald wieder einer Überarbeitung bedurft.

Fazit
Als modular und betriebssystemübergreifende Technologie ist Microsoft mit ASP.NET Core 1.0 auf dem richtigen Weg. Die Technologie ist derzeit allerdings noch im Entstehen, dementsprechend dürftig sieht es auch in Sachen Dokumentation und Codebeispielen aus. Für eine Portierung unserer bestehenden Web API nach ASP.NET Core ist es deshalb noch etwas zu früh. Wenn ich die Entscheidung über die Wahl des zu verwendenden ASP.NET-Frameworks für die Entwicklung einer neuen ASP.NET Website treffen könnte, so würde ich wohl bis auf Weiteres den sicheren, bereits erprobten Weg gehen: ASP.NET 4.6.

Referenzen
1. http://www.hanselman.com/blog/ASPNET5IsDeadIntroducingASPNETCore10AndNETCore10.aspx

2. http://dzimchuk.net/post/bring-your-own-di-container-to-aspnet-5-unity

3. http://www.fueltravel.com/blog/unity-dependency-injection-in-asp-net-mvc-vnext/

4. http://stackoverflow.com/questions/30553991/asp-net-5-jwt-bearer-token-flow

5. http://stackoverflow.com/questions/32886387/jwt-authentication-in-asp-net-5-using-oauthbearerauthentication

ASP.NET Core 1.0 – jetzt auf allen Plattformen?

ASP.NET Core 1.0, der noch im Entstehen befindliche Nachfolger von ASP.NET 4.x, ist ebenso modular, quelloffen und betriebssystemübergreifend wie das neue .NET Core. Was bringt uns das neue ASP.NET und wird es uns demnächst ermöglichen, auch auf Linux und OS X lauffähige Websites zu entwickeln wie bisher für Windows?

Einleitung
In meinem vorherigen Artikel gab ich einen Überblick über .NET Core 1.0 – Microsofts neue, wenngleich noch unfertige, plattform- und betriebssystemübergreifende Technologie, die womöglich in der Zukunft das herkömmliche, nur auf Windows lauffähige .NET Framework ersetzen wird. Dies betrifft allerdings auch alle auf dem Core aufbauenden Frameworks, die entweder ebenso neu entwickelt oder nach .NET Core portiert werden müssen.

ASP.NET Core 1.0
ASP.NET Core 1.0 ist eines der ersten Frameworks, die auf Core aufbauen, welches analog zu .NET Core die neueste Version der ASP.NET-Familie darstellt und ebenso noch in Entwicklung ist. Es ist ebenfalls modular aufgebaut (Komponenten per NuGet beziehbar), quelloffen, plattform- und betriebssystemübergreifend verfügbar.

Neuerungen und Unterschiede zum Vorgänger
Zwar unterstützt ASP.NET Core 1.0 MVC- und WebAPI-Projektvorlagen, doch deren Implementierung unterscheidet sich von ASP.NET 4.6. Im neuen ASP.NET wurden nämlich die einst unterschiedlichen Controller-Implementierungen – ApiController (Web API 2) aus dem System.Web.Http- und Controller (MVC 5) aus dem System.Web.Mvc-Namespace – in einen Controller (MVC 6) vereint. Die Unterstützung für SignalR und Web Pages wurde bereits angekündigt. Dies lässt sich allerdings nicht für WebForms sagen. Es ist durchaus vorstellbar, dass diese Technologie überhaupt nicht nach ASP.NET Core 1.0 portiert werden wird.

In der neusten Version hat sich auch die Projektstruktur geändert. Manche Dateien wurden fallengelassen und neue eingeführt, welche die bisherigen Information und Logik in kleineren, auf den konkreten Konfigurationszweck fokussierten Dateien enthalten. Des Weiteren hat Microsoft gänzlich auf XML als Format für Konfigurationsdateien verzichtet und ist an seiner Stelle auf JSON umgestiegen. Der Grund für diese Strukturänderungen war, dass bislang zu viel Konfiguration über „web.config“ und „packages.config“ sowie die Projektdatei selbst stattfand.

ASP.NET Core 1.0 verwendet standardmäßig seinen eigenen, eine minimale Funktionalität aufweisenden Dependency Injection Container, welcher aber nicht andere Container ersetzen soll. Bisher gibt es noch keinen passenden Bootstrapper für Unity, weswegen sich man sich bisweilen nach einem anderen Container (z.B. AutoFac) umschauen muss, sofern die Funktionalität des von Hause mitgelieferten DI-Containers nicht ausreicht.

Das Beste aus beiden Welten
Obwohl der Name „Core“ dies suggeriert, gilt nicht zwangsläufig, dass man .NET Core in Kombination mit ASP.NET Core verwenden muss. Wenn man in ASP.NET Core 1.0 entwickelt, kann man nämlich für beide Laufzeitumgebungen gleichzeitig entwickeln – sowohl für das „alte“ .NET Framework als auch für .NET Core (siehe Abbildung 1).

Abbildung 1 – Auswahlmöglichkeiten der Laufzeitumgebung für ASP.NET Core 1.0 und ASP.NET 4.6 [2]

Falls die bisher nach .NET Core 1.0 portierte Funktionalität nicht ausreichen oder manche Programmbibliotheken nicht mit .NET Core kompatibel sein sollten, kann man in den Projekteinstellungen aus den zu unterstützenden Frameworks einfach .NET Core entfernen und weiterhin nur für .NET Framework 4.6 entwickeln. Im Endeffekt hat man also das vollständige .NET Framework zur Verfügung und kann trotzdem ASP.NET Core 1.0 Anwendungen schreiben.

Core oder Nicht-Core – das ist hier die Frage
Laut Scott Hanselman [2] sollte man bei der Wahl des zu verwendenden ASP.NET-Frameworks bedenken, dass es sich bei ASP.NET 4.6 um die ausgereiftere Plattform handelt, da praxiserprobt und bereits heute verfügbar. Von ASP.NET Core 1.0 dagegen gibt es gerade mal das erste Release, das bis jetzt lediglich Web API und MVC-Projekte unterstützt. Obwohl ASP.NET Core 1.0 den Beginn eines neuen Kapitels darstellt, wird ASP.NET 4.6 bis auf Weiteres voll unterstützt und auch weiterentwickelt.

In einem nachfolgenden Artikel werde ich diese Kernfrage noch im Kontext eines Portierungsversuchs unserer hauseigenen Web API detaillierter beleuchten.

Fazit
Im Zusammenspiel mit dem betriebssystemübergreifenden .NET Core 1.0 versucht Microsoft, ASP.NET Core 1.0 auch auf Linux und OS X verfügbar zu machen. Das neue ASP.NET kennt keine Unterscheidung zwischen Web API- und MVC-Controllern mehr und basiert nur noch auf MVC 6. Es kann auch auf dem vollständigen, „alten“ .NET Framework laufen, welches mehr Funktionalität bietet, praxiserprobt und voll ausgereift ist. Man kann deshalb ohne Weiteres auch ASP.NET 4.6 weiterhin verwenden.

Referenzen

1. http://docs.asp.net/en/latest/conceptual-overview/understanding-aspnet5-apps.html
2. http://www.hanselman.com/blog/ASPNET5IsDeadIntroducingASPNETCore10AndNETCore10.aspx

.NET nun auf Linux, OS X und Windows?

Der Weg, den Microsoft mit dem neuen, modularen, quelloffenen, auf Linux, OS X und Windows lauffähigen .NET Core gerade geht, könnte ein neues Kapitel aufschlagen.

Einleitung
Seit der ersten Veröffentlichung des .NET Frameworks in 2002 besteht dieses in verschiedenen, fragmentierten Ausgaben je nach Anwendungstyp. Aufgrund seiner fehlenden Modularität hat die Einführung einer neuen .NET-Version und deren Portierung auf eine bestimmte Plattform (Mobile, Web, Desktop, usw.) in der Vergangenheit immer ein neues Anwendungsmodell, Framework und eine neue Laufzeitumgebung mit sich gebracht (siehe Abbildung 1). Es bildete deshalb eine monolithische Einheit, welche immer im Betriebssystem zu installieren war. Dies ist nicht unproblematisch: Erstens kann sich die Installation einer neuen .NET-Version immer auf das Verhalten bestehender Anwendungen auswirken, und zweitens ist es Softwareentwicklern nicht immer möglich und erlaubt, ein .NET-Upgrade auf dem Zielsystem bei Bedarf selbst vorzunehmen.


Abbildung 1 – Fragmentiertes .NET Framework auf verschiedenen Plattformen [2]

.NET Core 1.0
Im Mai 2014 kündigte Microsoft die Entwicklung des betriebssystemübergreifenden ASP.NET Core 1.0 an, was allerdings auch die Entwicklung eines neuen .NET Frameworks – .NET Core 1.0 – erforderte. Im Gegensatz zum klassischen, monolithischen .NET Framework ist .NET Core modular aufgebaut.

Dies ermöglicht die selektive Verwendung der .NET-Komponenten, die auch tatsächlich im Anwendungsprojekt benötigt werden. Bei .NET Core gehören die oben beschriebenen Probleme deshalb der Vergangenheit an, denn die benötigten Einzelkomponenten sind anwendungsspezifisch und können einfach über ein NuGet-Paket bezogen werden, was keinerlei Auswirkungen auf andere Anwendungen hat.

Des Weiteren ist .NET Core eine quelloffene, plattform- und betriebssystemübergreifende, d. h. sowohl auf Windows, OS X als auch auf Linux lauffähige Neuimplementierung des .NET Frameworks, welche sich unter der Federführung von Microsoft derzeit noch in Entwicklung befindet.

Dementsprechend enthält .NET Core derzeit nur einen Teil der bisherigen .NET-Funktionalität, da Teile des vollständigen .NET Frameworks noch nicht abschließend portiert sind. Auf eine vollständige Übernahme aller bisher zur Verfügung stehenden Funktionen wird man allerdings vergeblich warten, denn Microsoft hat manche Features für .NET Core bereits abgekündigt. Dazu gehören unter anderem:

  • App Domains
  • Remoting
  • Sandboxing

Wer bereits für das neue Framework entwickeln möchte, kann das mit UWP-Anwendungen tun, denn die laufen bereits auf .NET Core. Gleichermaßen können auch Web API- und MVC-Websites unter ASP.NET Core 1.0 erstellt werden, das ebenso auf .NET Core lauffähig ist.

Spielt man mit dem Gedanken, vorhandene Anwendungen auf das neue Framework zu portieren, so sind derzeit vor allem Konsolenanwendungen sowie auf MVC oder Web API basierende ASP.NET-Anwendungen geeignete Kandidaten, denn letztere werden in einer ähnlichen Form im ASP.NET Core 1.0 bereits jetzt unterstützt. Anders sieht das allerdings bei bestehenden WebForms- oder WPF-Anwendungen aus. Bis jetzt gibt es seitens Microsoft noch keine offizielle Aussage dazu, ob und wann diese nach .NET Core portiert werden.

Wie nenne ich mein Kind?
Wer im Internet nach „.NET Core“ sucht, der wird teilweise noch die vormals von Microsoft selbst verwendeten Benennungen – .NET Core 5, ASP.NET vNext und ASP.NET 5 – finden. Diese wurden letztlich fallengelassen, erweckten sie doch den Anschein, sie seien besser und ersetzten die früheren Versionen. Die neue Namensgebung soll die grundlegende Neuausrichtung bei .NET Core und ASP.NET Core im Namen transportieren.

Fazit
Das neue .NET Core 1.0 ist eine modulare, plattform- und betriebssystemübergreifende Neuimplementierung des .NET Frameworks, die derzeit noch entwickelt wird. Durch seine Modularität haben Entwickler die Möglichkeit, gewünschte Einzelkomponenten per NuGet zu beziehen, anstatt im Betriebssystem ein .NET-Upgrade vornehmen zu müssen.

.NET Core 1.0 bringt Stand heute allerdings nur einen Teil der Funktionalität des vollständigen .NET Frameworks mit, weswegen sein Anwendungsbereich zurzeit auf ASP.NET Core 1.0-, UWP- und Konsolenanwendungen beschränkt ist. Eine offizielle Aussage seitens Microsoft zur Portierung weiterer Technologien wie z.B. WPF, WebForms, usw. gibt es noch nicht, man darf aber gespannt sein.

Referenzen

  1. https://msdn.microsoft.com/de-de/library/dn878908(v=vs.110).aspx
  2. http://thenewstack.io/why-you-should-care-about-the-new-open-source-net-core/
  3. https://blogs.msdn.microsoft.com/dotnet/2016/02/10/porting-to-net-core/