ASP.NET Core ohne klassisches .NET Framework nutzen

ASP.NET Core ohne klassisches .NET Framework nutzen

Mit .NET Core hat Microsoft den wohl bisher größten Schritt seit der Geschichte des Frameworks gewagt: Das Framework ist nicht nur quelloffen, sondern läuft auf allen gängigen Plattformen. Neben Windows also auch Linux und OS X (Mac). Nun lässt sich das neue .NET Core aber auch mit dem alten, klassischen .NET 4.6 kombinieren. Dies kann beispielsweise als Übergang zur Portierung einer älteren Anwendung sinnvoll sein. Oder wenn man Bibliotkenen benötigt, die noch nicht mit .NET Core kompatibel sind.

Zumindest langfristig ist dies aber nicht empfehlenswert, da die wichtigsten Neuerungen von .NET Core so nicht genutzt werden können:

  • Plattformunabhängigkeit
  • Leichtgewichtiger Kern mit modularem Aufbau

Hierfür muss man für seine Anwendung vollständig auf Core setzen. Damit wird es beispielsweise möglich, eine ASP.NET Core Webanwendung auf einem Linux-Server zu betreiben. Im Folgenden wird gezeigt, worauf geachtet werden muss. Ausgangspunkt ist ein leeres ASP.NET Core Projekt, das mittels Visual Studio Vorlage erstellt und auf die derzeit aktuellste Version (1.1.0) aktualisiert wurde.

Das Ziel: Die Anwendung soll unabhängig von sämtlicher Microsoft-Proprietären Software (Windows, IIS, usw) agieren.

Anpassung des Zielframeworks

Dies ist der wohl wichtigste Punkt. Wie schon erwähnt, können wir in einer .NET Core Anwendung das Zielframework festlegen. Dies geschieht im Schlüssel frameworks der project.json Konfigurationsdatei. In einem aktuellen ASP.NET Core 1.1.0 Projekt sieht dieser meist wie folgt aus:

"frameworks": {
    "netcoreapp1.1": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.1.0"
        }
      },
      "imports": "dnxcore50"
    }
  }

Hier wird festgelegt, dass die Anwendung .NET Core 1.1.0 als Zielframework besitzt. Man kann sich diesen Abschnitt analog zur Auswahl des Zielframeworks in den Projekteigenschaften einer klassischen .NET Windows-Anwendung vorstellen. Dort konnte man beispielsweise .NET Framework 3.5 auswählen, damit die Anwendung auch auf älteren Frameworks läuft. Die Funktionen der Nachfolger wie .NET 4.5 standen dann allerdings nicht zur Verfügung.

Im Prinzip erledigt dieser Konfigurationsabschnitt die gleiche Aufgabe. Einziger Unterschied: Mit .NET Core ist es möglich, mehrere Laufzeitumgebungen zu definieren. Über Präprozessor-Anweisungen kann z.B. Windows-Spezifischer Code nur auf .NET 4.6 ausgeführt werden. Dies wird allerdings ausdrücklich seitens Microsoft nicht empfehlen, da es verschiedene Risiken birgt. Darauf möchte ich auch nicht weiter eingehen, weil es für unser Ziel nichts zur Sache tut.

Anpassung des Zielframeworks

Es existieren eine ganze Reihe von Zielframeworks. Im Folgenden möchte ich daher nur kurz auf die wichtigsten drei eingeben. Eine vollständige, von Microsoft gepflegte Liste ist hier zu finden: Target Frameworks

.NET Standard: netstandard1.2, netstandard 1.5

Microsofts Ansatz, ein Basisframework zu schaffen. Dies soll auf allen .NET Implementierungen gleich sein, und so die Fragmentierung verhindern. Im Gegensatz zu .NET Core sind hier nicht nur Desktop- und Server-Betriebssysteme gemeint. Sondern auch unterschiedliche Gerätetypen wie beispielsweise Smartphones oder Spielekonsolen.

.NET Core: netcoreapp1.0, netcoreapp1.1

Bezieht sich auf das neue .NET Core, welches sowohl auf Windows, Linux als auch Mac OS läuft. Viele Schnittstellen basieren auf dem klassischen .NET, wenngleich nicht alle verfügbar sind (z.B. System.Drawing). Auch durch neue Entwicklungsmuster wie Dependency Injection statt statischer Eigenschaften ist klassischer .NET Core nicht ohne Anpassungen kompatibel.

Klassisches .NET Framework: net45, net451, net46, net461

Referenziert das alte, klassische .NET Framework, wie wir es bis zum Release von .NET Core kannten. Die Versionsnummern entsprechen auch hier denen der Release, allerdings ohne Punkt. Wer .NET 4.6.1 referenzieren möchte, gibt also net461 an.

Als Konsequenz bedeutet dies: Wir dürfen nur .NET Core oder .NET Standard referenzieren. Ansonsten ist unsere Anwendung nicht mehr plattformunabhängig. Wer an dieser Stelle mehr über den interessanten .NET Standard Ansatz erfahren möchte, sollte einen Blick in die .NET Standard FAQ werfen.

Sollte man den IIS entfernen?

Ein neues ASP.NET Core Projekt wird in den IIS integriert. Allerdings nicht als plattformspezifisches Modul, wie wir es von den alten ASP.NET Stacks kennen. Stattdessen bringt ASP.NET Core mit Kestrel einen eingebauten Webserver mit. Gemäß des modularen Ansatzes ist er sehr rudimentär, und bietet nur den Bruchteil eines vollwertigen Webservers wie IIS, Apache oder Nginx. Wer weitreichendere Konfiguration benötigt, muss daher einen der genannten Webserver als Reverse Proxy einsetzen.

Hierfür kann man natürlich den IIS nehmen. Das macht aber nur Sinn, wenn die Anwendung zwangsläufig auf einem Windows Server laufen muss – beispielsweise aufgrund von alten Abhängigkeiten, die noch nicht zum plattformübergreifenden .NET Core portiert wurden.

In allen anderen Fällen macht es Sinn, zumindest über Linux nachzudenken: Man setzt auf offene Software, die kontrollierbar ist – wir erinnern uns an den NSA-Skandal. Der Quellcode eines proprietären Betriebssystemes wie Windows ist geheim, sodass sich darin auch unerwünschtes befinden kann. Beispielsweise Hintertüren oder Spionagefunktionen. Linux ist hier wesentlich transparenter und unabhängig Darüber hinaus ist Linux sehr anpassungsfähig und es werden keine Lizenzgebühren fällig. Microsoft kann die Preise jederzeit ändern. Ist man darauf angewiesen, hat man keine andere Wahl, als diese zu bezahlen. Wer das für ein theoretisches Szenario hält, sollte mal recherchieren, was sich alleine im Preismodell der neuen Windows Server geändert hat. Spätestens wenn die alten Versionen keine Updates mehr erhalten, bleibt keine andere Wahl. Die alten Preise genießt man nur noch maximal ein paar Jahre. Das Thema möchte ich an dieser Stelle aber nicht ausweiten. Zum IIS sei noch gesagt, dass der Betrieb ohne IIS unter Linux deutlich schlanker vonstatten geht. Vor allem in Kombination mit Docker. Dies verbessert die Leistung, während Ressourcenverbrauch und Angriffsfläche reduziert werden.

So wird der IIS aus ASP.NET Core 1.x entfernt

Im Standard-Template wird.UseIISIntegration()in Program.cs ausgeführt und so das IIS-Modul geladen:

public class Program
{
    public static void Main(string[] args)
    {
        var config = new ConfigurationBuilder()
            .AddCommandLine(args)
            .AddEnvironmentVariables(prefix: "ASPNETCORE_")
            .Build();

        var host = new WebHostBuilder()
            .UseConfiguration(config)
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();

        host.Run();
    }
}

Hier entfernt man einfach die Zeile .UseIISIntegration() und hat damit alle IIS-Abhängigkeiten entfernt. Beim Debuggen in Visual Studio ist darauf zu achten, dass auch hier der integrierte Kestrel-Webserver zum Einsatz kommt. Zu erkennen am Anwendungsname neben dem Debug-Button. Steht dort IIS, ist das nicht der Fall. Da genau das die Standardeinstellung ist, debuggt man in diesem Falle mit dem IIS Express. Dieser wird von Visual Studio automatisch im Hintergrund gestartet. Das ist natürlich wenig sinnvoll, da man so mit einem anderen Webserver arbeitet, der später produktiv gar nicht zum Einsatz kommt. Darüber hinaus startet Kestrel auch schneller als der IIS, da er deutlich schlanker ist.

Leave a Reply