ASP.NET

Topshelf und Katana: Eine einheitliche Web- und Servicearchitektur

Wes McClure

Laden Sie die Codebeispiele herunter

Der Einsatz von IIS für das Hosting von ASP.NET Webanwendungen war über ein Jahrzehnt lang der Standard. Eine solche Anwendung zu entwickeln ist ein relativ einfacher Prozess; die Bereitstellung hingegen ist das nicht. Das Bereitstellen erfordert eine kuratierte Kenntnis der Konfigurationshierarchien von Anwendungen sowie der Nuancen in der Geschichte von IIS. Dazu kommt das mühsame Einrichten von Sites, Anwendungen und virtuellen Verzeichnissen. Viele der kritischen Teile der Infrastruktur führen am Ende dann ein Eigenleben außerhalb der Anwendung in manuell konfigurierten IIS-Komponenten.

Wenn Anwendungen einfachen Webanfragen entwachsen und Anfragen mit langer Laufzeit, sich wiederholende Jobs und andere verarbeitende Aufgaben unterstützen sollen, dann wird die Unterstützung mit IIS sehr schwierig. Die Lösung besteht häufig darin, einen separaten Windows Service zu erstellen, der diese Komponenten hostet. Doch das erfordert einen ganz separaten Deployment-Prozess, was den damit verbundenen Aufwand verdoppelt. Der letzte Strohhalm besteht darin, die Web- und Serviceprozesse miteinander kommunizieren zu lassen. Was eine sehr einfache Anwendung sein könnte, wird plötzlich extrem komplex.

Abbildung 1 stellt dar, wie diese Architektur typischerweise aussieht. Die Webschicht ist verantwortlich für den Umgang mit schnellen Anfragen und stellt dem System eine UI zur Verfügung. Anfragen mit langer Laufzeit werden an den Service delegiert, der auch sich wiederholende Jobs und die Verarbeitung übernimmt. Außerdem liefert der Service den Status über aktuelle und künftige Aufgaben der Webschicht, die im UI enthalten sein sollen.

Traditional Separated Web and Service Architecture
Abbildung 1: Traditionelle, getrennte Web- und Servicearchitektur

Ein neuer Ansatz

Glücklicherweise tauchen neue Technologien am Horizont auf, die das Entwickeln und Bereitstellen erheblich vereinfachen. Dank des Katana-Projekts (katanaproject.codeplex.com) und der von OWIN bereitgestellten Spezifikationen (owin.org) ist es jetzt möglich, Webanwendungen selbst zu hosten, was IIS aus der Gleichung entfernt. Viele der überall vorhandenen ASP.NET-Komponenten wie beispielsweise WebApi und SignalR werden dabei weiterhin unterstützt. Das Web-Self-Hosting lässt sich in einer rudimentären Konsolenanwendung zusammen mit Topshelf (topshelf-project.com) einbetten, wodurch sich einfach ein Windows Service erstellen lässt. Im Ergebnis können Web- und Servicekompnenten im selben Prozess nebeneinander existieren, wie in Abbildung 2 dargestellt. Das eliminiert den zusätzlichen Aufwand für das Entwickeln überflüssiger Kommunikationsschichten, separater Projekte und Bereitstellungsverfahren.

Unified Web and Service Architecture with Katana and Topshelf
Abbildung 2: Einheitliche Web- und Servicearchitektur mit Katana und Topshelf

Diese Möglichkeit ist nicht völlig neu. Topshelf gibt es seit Jahren, und es vereinfacht die Entwicklung von Windows Service. Außerdem existieren viele Open-Source-Web-Frameworks für Self-Hosting wie beispielsweise Nancy. Bis allerdings OWIN die Bühne des Katana-Projekts betrat, gab es nichts, das so vielversprechend war, als dass es die de facto Standardalternative für das Hosting von Webanwendungen in IIS hätte werden können. Mehr noch, Nancy und viele der Open-Source-Komponenten arbeiten mit dem Katana-Projekt. So ist es möglich, eklektische, anpassungsfähige Frameworks zu kuratieren.

Topshelf mag optional erscheinen, aber das stimmt nicht. Ohne die Möglichkeit einer vereinfachten Dienstentwicklung kann die selbst gehostete Webentwicklung eine extrem mühsame Angelegenheit werden. Topshelf macht das Entwickeln des Dienstes einfacher, weil es ihn als Konsolenanwendung behandelt und die Tatsache abstrahiert, dass er als Dienst gehostet wird. Wenn die Zeit für die Bereitstellung gekommen ist, übernimmt Topshelf automatisch die Installation und startet die Anwendung als Windows Service – und das ganz ohne den zusätzlichen Aufwand, mit InstallUtil arbeiten zu müssen, die Nuancen eines Dienstprojekts und der Dienstkomponenten sowie dem Anhängen von Debuggern an Dienste, wenn etwas schief läuft. Topshelf ermöglicht auch viele Parameter wie beispielsweise den Dienstnamen im Code festzulegen oder während der Installation per Kommandozeile zu konfigurieren.

Um die Zusammenfassung von Web- und Dienstkomponenten mit Katana und Topshelf zu illustrieren, entwickle ich eine einfache SMS-Messaging-Anwendung. Ich fange mit einer API an, mit der Nachrichten empfangen und in eine Warteschlange für das Versenden eingereiht werden können. Damit lässt sich zeigen, wie einfach es ist, Anfragen mit langer Laufzeit zu verarbeiten. Dann füge ich eine API-Abfragemethode hinzu, die die Anzahl der ausstehenden Nachrichten ausgibt. Damit lässt sich zeigen, dass es auch einfach ist, den Dienststatus von Webkomponenten abzufragen.

Als Nächstes baue ich eine administrative Schnittstelle ein, was demonstriert, dass selbst gehostete Webkomponenten die Entwicklung voll ausgestatteter Webschnittstellen erlauben. Zur Abrundung der Nachrichtenverarbeitung füge ich eine Komponente hinzu, die Nachrichten beim Einstellen in die Warteschlange versendet und so die Integration von Dienstkomponenten verdeutlicht.

Und um einen der besten Teile dieser Architektur aufzuzeigen, erstelle ich ein psake-Skript, mit dem das einfache Bereitstellen erkennbar wird.

Weil der Schwerpunkt auf den Vorteilen einer Kombination von Katana und Topshelf liegt, gehe ich nicht in die Details des jeweiligen Projekts. Siehe „Erste Schritte mit dem Katana-Projekt”(https://msdn.microsoft.com/de-de/magazine/dn451439.aspx) und „Create Windows Services Easily with Topshelf” (bit.ly/1h9XReh), wo Sie mehr erfahren.

Für den Anfang brauchen Sie lediglich eine Konsolenanwendung

Topshelf gibt es, damit sich Windows Services vom Ausgangspunkt einer simplen Konsolenanwendung einfach entwickeln und bereitstellen lassen. Als ersten Schritt mit der SMS-Messaging-Anwendung erstelle ich eine C#-Konsolenanwendung und installiere dann das Topshelf NuGet-Paket aus der Paket-Manager-Konsole.

Wenn die Konsolenanwendung startet, muss ich die Topshelf HostFactory konfigurieren, damit das Hosting der Anwendung als Konsole in der Entwicklung und als Dienst in der Produktion abstrahiert wird:

private static int Main() { var exitCode = HostFactory.Run(host => { }); return (int) exitCode; }

Die HostFactory gibt einen Exitcode aus, was während der Dienstinstallation hilfreich ist, da Fehler erkannt und dann gestoppt wird. Der Host-Konfigurator stellt eine Dienstmethode bereit, mit der sich ein benutzerdefinierter Typ festlegen lässt, der den Einstiegspunkt Ihres Anwendungscodes darstellt. Topshelf verweist darauf als den Service, den es hostet, denn Topshelf ist ein Framework, mit dem das Erstellen des Windows Service vereinfacht wird:

host.Service<SmsApplication>(service => { });

Als nächstes erstelle ich einen Typ SmsApplication, der die Logik enthält, mit der man den selbst gehosteten Webserver und die traditionellen Windows Service-Komponenten zum Laufen bringt. Dieser benutzerdefinierte Typ enthält mindestens das auszuführende Verhalten bei Start oder Beenden der Anwendung:

public class SmsApplication { public void Start() { } public void Stop() { } }

Weil ich mich für ein Plain Old CLR Object (POCO) als Diensttyp entschieden habe, gebe ich einen lambda-Ausdruck an Topshelf, sodass eine Instanz vom Typ SmsApplication konstruiert wird. Außerdem lege ich die Start- und Stop-Methode fest:

service.ConstructUsing(() => new SmsApplication()); service.WhenStarted(a => a.Start()); service.WhenStopped(a => a.Stop());

Topshelf lässt das Konfigurieren vieler Dienstparameter im Code zu, weshalb ich SetDescription, SetDisplayName und SetServiceName verwende, um den Dienst zu beschreiben und zu benennen, der in der Produktion installiert wird:

host.SetDescription("An application to manage sending sms messages and provide message status."); host.SetDisplayName("Sms Messaging"); host.SetServiceName("SmsMessaging"); host.RunAsNetworkService();

Schließlich verwende ich RunAsNetworkService und weise Topshelf damit an, den Dienst so zu konfigurieren, dass er als Netzwerkdienstkonto läuft. Sie können das so ändern, dass es auf das jeweils passende Konto in Ihrer Umgebung passt. Weitere Dienstoptionen finden Sie in Topshelf-Konfigurationsdokumentation unter bit.ly/1rAfMiQ.

Den Dienst als Konsolenanwendung zu betreiben ist so einfach wie das Starten der ausführbaren Datei. Abbildung 3 zeigt, wie die Ausgabe die ausführbare SMS-Datei startet und stoppt. Weil dies eine Konsolenanwendung ist, tritt dasselbe Verhalten auf, wenn Sie sie in Visual Studio starten.

Running the Service as a Console Application
Abbildung 3: Den Dienst als Konsolenanwendung betreiben

Eine API integrieren

Nachdem Topshelf eingerichtet ist, kann ich die Arbeit mit der API der Anwendung beginnen. Das Katana-Projekt stellt Komponenten für das Self-Hosting einer OWIN-Pipeline bereit. Ich installiere also das Microsoft.Owin.SelfHost-Paket und integriere die Self-Hosting-Komponenten. Dieses Paket referenziert eine Reihe von Paketen, von denen zwei für das Self-Hosting wichtig sind. Erstens stellt Microsoft.Owin.Hosting ein Set von Komponenten bereit, mit denen sich eine OWIN-Pipeline hosten und ausführen lässt. Zweitens liefert Microsoft.Owin.Host.HttpListener eine Implementierung eines HTTP-Servers.

In der SmsApplication erstelle ich eine selbst gehostete Webanwendung mithilfe des Typs WebApp, der vom Hostingpaket bereitgestellt wird:

protected IDisposable WebApplication; public void Start() { WebApplication = WebApp.Start<WebPipeline>("http://localhost:5000"); }

Die Startmethode WebApp erfordert zwei Parameter, einen generischen zur Festlegung eines Typs, den ich in der OWIN-Pipeline konfiguriere, und eine URL, auf der auf Anfragen gewartet wird. Die Webanwendung ist eine verwerfbare Ressource. Wenn die Instanz der SmsApplication gestoppt wird, verwerfe ich die Webanwendung:

public void Stop() { WebApplication.Dispose(); }

Ein Vorteil beim Einsatz von OWIN besteht darin, dass ich eine Menge bekannter Komponenten nutzen kann. Als erstes verwende ich WebApi und erstelle die API. Ich muss das Paket Microsoft.AspNet.WebApi.Owin installieren, damit WebApi in der OWIN-Pipeline integriert ist. Dann erstelle ich den Typ WebPipeline, konfiguriere die OWIN-Pipeline und ergänze die WebApi Middleware. Zusätzlich konfiguriere ich WebApi so, dass Attribut-Routing verwendet wird:

public class WebPipeline { public void Configuration(IAppBuilder application) { var config = new HttpConfiguration(); config.MapHttpAttributeRoutes(); application.UseWebApi(config); } }

Und nun kann eine API-Methode erstellen, mit der ich Nachrichten empfangen und sie in die Warteschlange zum Versenden stellen kann:

public class MessageController : ApiController { [Route("api/messages/send")] public void Send([FromUri] SmsMessageDetails message) { MessageQueue.Messages.Add(message); } }

SmsMessageDetails enthält den eigentlichen Inhalt der Nachricht. Die Sendeaktion fügt die Nachricht einer Warteschlange hinzu, sodass sie später asynchron verarbeitet wird. Die MessageQueue ist eine globale BlockingCollection. In einer echten Anwendung könnte das heißen, dass Sie andere Überlegungen einbeziehen müssen wie beispielsweise Dauerhaftigkeit und Skalierbarkeit:

public static readonly BlockingCollection<SmsMessageDetails> Messages;

In einer getrennten Web- und Dienstarchitektur erfordert das Übergeben der asynchronen Verarbeitung von Anfragen mit langer Laufzeit, wie beispielsweise das Versenden einer Nachricht, eine Kommunikation zwischen den Web- und Dienstprozessen. Und das Hinzufügen von API-Methoden zur Statusabfrage des Dienstes bedeutet sogar noch mehr Kommunikationsaufwand. Ein zusammengefasster Ansatz macht das Teilen von Statusinformationen zwischen Web- und Dienstkomponenten einfach. Ich demonstriere das, indem ich eine PendingCount-Abfrage zur API hinzufüge:

[Route("api/messages/pending")] public int PendingCount() { return MessageQueue.Messages.Count; }

Eine Benutzeroberfläche entwickeln

APIs sind praktisch, doch müssen selbst gehostete Webanwendungen immer noch eine visuelle Schnittstelle unterstützen. Ich gehe davon aus, dass künftig der ASP.NET MVC-Framework oder ein Derivat als OWIN-Middleware verfügbar sein wird. Für den Moment ist Nancy kompatibel und verfügt über ein Paket, mit dem der Kern des Razor-Ansichtsmoduls unterstützt wird.

Ich installiere das Nancy.Owin-Paket und füge damit die Unterstützung für Nancy hinzu, sowie Nancy.Viewengines.Razor, damit das Razor-Ansichtsmodul integriert ist. Damit Nancy Teil der OWIN-Pipeline wird, muss ich es nach der Registrierung für WebApi registrieren, damit es nicht die Routen in Beschlag nimmt, die ich der API zugewiesen habe. Standardmäßig gibt Nancy einen Fehler aus, wenn eine Ressource nicht gefunden wird, während WebApi die Anfrage, die sie nicht verarbeiten kann, zurück an die Pipeline gibt:

application.UseNancy();

Mehr über den Einsatz von Nancy mit einer OWIN-Pipeline erfahren Sie in „Hosting Nancy with OWIN” unter bit.ly/1gqjIye.

Für die Entwicklung einer administrative Statusschnittstelle füge ich ein Nancy-Modul hinzu und ordne eine Statusroute zu, die eine Statusansicht rendert. Sie gibt die Anzahl der ausstehenden Nachrichten an das Anzeigemodell weiter:

public class StatusModule : NancyModule { public StatusModule() { Get["/status"] = _ => View["status", MessageQueue.Messages.Count]; } }

Die Ansicht ist im Moment nicht berauschend, nur einfach die Anzahl ausstehender Nachrichten:

    <h2>Status</h2> Es stehen <strong>@Model</strong> Nachrichten aus.

Die Ansicht möble ich jetzt etwas mit einer einfachen Bootstrap-Navbar aufpeppen, wie in Abbildung 4 dargestellt. Der Einsatz von Bootstrap erfordert das Hosting von statischem Inhalt für das Bootstrap-Stylesheet.

Administrative Status Page
Abbildung 4: Die Seite Administrationsstatus

Ich könnte Nancy für das Hosting von statischem Inhalt verwenden, doch der Vorteil von OWIN liegt im Mischen und Anpassen von Middleware. Deshalb verwende ich stattdessen das kürzlich veröffentlichte Paket Microsoft.Owin.StaticFiles, das Teil des Katana-Projekts ist. Das Paket StaticFiles liefert die Middleware für das File-Serving. Ich füge es hinzu, um die OWIN-Pipeline zu starten, sodass das statische File-Serving von Nancy nicht greift.

application.UseFileServer(new FileServerOptions { FileSystem = new PhysicalFileSystem("static"), RequestPath = new PathString("/static") });

Der Parameter FileSystem sagt dem Dateiserver, wo er nach den bereitzustellenden Dateien suchen soll. Ich verwende einen Ordner namens static. Der RequestPath legt den Routenpräfix für das Warten auf Anfragen für diesen Inhalt fest. In diesem Fall habe ich entschieden, den Namen static zu spiegeln; das muss aber nicht unbedingt gleich sein. Ich verwende den folgenden Link im Layout als Referenz für das Bootstrap-Stylesheet (natürlich platziere ich dieses Stylesheet in einen CSS-Ordner im statischen Ordner):

    <link rel="stylesheet" href="/static/css/bootstrap.min.css">

Ein Wort zu statischen Inhalten und Ansichten

Ehe wir fortfahren, möchte ich Ihnen von einem Tipp verraten, den ich beim Entwickeln einer selbst gehosteten Webanwendung hilfreich finde. Normalerweise würde man den statischen Inhalt und die MVC-Ansichten so einstellen, dass sie direkt in das Ausgabeverzeichnis kopiert werden, sodass die selbst gehosteten Webkomponenten sie relativ zum aktuell ausgeführten Assembly finden können. Das ist nicht nur mühsam und wird leicht vergessen, sondern das Ändern der Ansicht und des statischen Inhalts macht auch das erneute Kompilieren der Anwendung nötig – ein absoluter Produktivitätskiller. Ich empfehle deshalb, den statischen Inhalt und die Ansichten nicht in das Ausgabeverzeichnis zu kopieren, sondern stattdessen Middleware wie etwa Nancy zu konfigurieren sowie den FileServer, sodass dieser die Entwicklungsordner zuordnet.

Standardmäßig ist das Ausgabeverzeichnis einer Konsolenanwendung bin/Debug. In der Entwicklung sage ich also FileServer, zwei Verzeichnisse über dem aktuellen nachzusehen und dort den statischen Ordner zu finden, der das Bootstrap-Stylesheet enthält:

FileSystem = new PhysicalFileSystem(IsDevelopment() ? "../../static" : "static")

Dann erstelle ich einen benutzerdefinierten NancyPathProvider und sage Nancy damit, wo es nach den Ansichten suchen muss:

public class NancyPathProvider : IRootPathProvider { public string GetRootPath() { return WebPipeline.IsDevelopment() ? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\") : AppDomain.CurrentDomain.BaseDirectory; } }

Auch hier verwende ich dieselbe Prüfung und sehe zwei Verzeichnisse über dem Basisverzeichnis nach, wenn ich im Entwicklungsmodus von Visual Studio arbeite. Ich habe die Implementierung von IsDevelopment Ihnen überlassen; das kann eine einfache Konfigurationseinstellung sein oder Sie können auch Code schreiben, der überprüft, ob die Anwendung in Visual Studio gestartet wurde.

Um diesen benutzerdefinierten Pfadanbieter zu registrieren, erstelle ich einen benutzerdefinierten NancyBootstrapper und überschreibe die Standardeigenschaft RootPathProvider, sodass eine Instanz des NancyPathProvider erstellt wird:

public class NancyBootstrapper : DefaultNancyBootstrapper { protected override IRootPathProvider RootPathProvider { get { return new NancyPathProvider(); } } }

Und wenn ich Nance der OWIN-Pipeline hinzufüge, dann gebe ich eine Instanz von NancyBootstrapper in die Optionen weiter:

application.UseNancy(options => options.Bootstrapper = new NancyBootstrapper());

Nachrichten senden

Das Empfangen von Nachrichten ist die halbe Miete, doch braucht die Anwendung auch einen Prozess für das Versenden. Dieser Prozess würde traditionell in einem isolierten Dienst existieren. In dieser einheitlichen Lösung kann ich einfach einen SmsSender hinzufügen, der beim Start der Anwendung gestartet wird. Ich füge das der Startmethode SmsApplication hinzu (in einer echten Anwendung sollte man die Möglichkeit zum Stoppen und Verwerfen dieser Ressource integrieren):

public void Start() { WebApplication = WebApp.Start<WebPipeline>("http://localhost:5000"); new SmsSender().Start(); }

In der Startmethode starte ich auf SmsSender eine Aufgabe mit langer Laufzeit für das Versenden von Nachrichten:

public class SmsSender { public void Start() { Task.Factory.StartNew(SendMessages, TaskCreationOptions.LongRunning); } }

Wenn die Sendeaktion WebApi eine Nachricht empfängt, fügt sie diese einer Nachrichtenwarteschlange hinzu, die eine sperrende Auflistung ist. Ich erstelle die Methode SendMessages zum Sperren, bis die Nachrichten eintreffen. Das ist aufgrund der Abstraktion hinter GetConsumingEnumerable möglich. Wenn ein Set von Nachrichten eintrifft, werden diese sofort versandt:

private static void SendMessages() { foreach (var message in MessageQueue.Messages.GetConsumingEnumerable()) { Console.WriteLine("Sending: " + message.Text); } }

Es wäre trivial, mehrere Instanzen von SmsSender zum Laufen zu bringen und so die Möglichkeit auf das Senden von Nachrichten zu erweitern. In einer echten Anwendung sollte man einen CancellationToken an GetConsumingEnumerable weitergeben, sodass die Aufzählung sicher gestoppt wird. Wenn Sie mehr über das Sperren von Auflistungen erfahren möchten, finden Sie gute Informationen unter bit.ly/QgiCM7 und bit.ly/1m6sqlI.

Bereitstellung – locker und leicht

Kombinierte Dienst- und Webanwendungen zu entwickeln ist dank Katana und Topshelf relativ leicht und einfach. Zu den tollen Vorteilen dieser starken Kombination ist ein extrem einfacher Bereitstellungsprozess. Ich zeige Ihnen eine einfache Bereitstellung in zwei Schritten mit psake (github.com/psake/psake). Das soll kein robustes Skript für den tatsächlichen Einsatz in der Produktion sein. Ich möchte einfach demonstrieren, wie wirklich einfach der Prozess ist, ganz egal, welches Tool Sie verwenden.

Der erste Schritt besteht darin, die Anwendung zu entwickeln. Ich erstelle einen Buildtask, den ich msbuild nenne, mit Pfad zur Lösung und erstelle einen Releasebuild (die Ausgabe findet sich dann in bin/Release):

properties { $solution_file = "Sms.sln" } task build { exec { msbuild $solution_file /t:Clean /t:Build /p:Configuration=Release /v:q } }

Der zweite Schritt besteht darin, die Anwendung als Dienst bereitzustellen. Ich erstelle einen Bereitstellungstask, der vom Buildtask abhängt und gebe ein Zielverzeichnis an, das einen Pfad zum Installationsort enthält. Der Einfachheit halber stelle ich lediglich in ein lokales Verzeichnis bereit. Dann erstelle ich eine ausführbare Variable, die auf die ausführbare Datei der Konsolenanwendung im Zielverzeichnis verweist:

task deploy -depends build { $delivery_directory = "C:\delivery" $executable = join-path $delivery_directory 'Sms.exe'

Zuerst prüft der Bereitstellungstask, ob das Zielverzeichnis existiert. Wenn er ein solches findet, geht er davon aus, dass der Dienst schon bereitgestellt wurde. In diesem Fall deinstalliert der Bereitstellungstask den Dienst und entfernt das Zielverzeichnis:

if (test-path $delivery_directory) { exec { & $executable uninstall } rd $delivery_directory -rec -force }

Als Nächstes kopiert der Bereitstellungstask die Buildausgabe in das Zielverzeichnis und stellt damit den neuen Code bereit. Dann werden die Ansichten und statischen Ordner in das Zielverzeichnis kopiert:

copy-item 'Sms\bin\Release' $delivery_directory -force -recurse -verbose copy-item 'Sms\views' $delivery_directory -force -recurse -verbose copy-item 'Sms\static' $delivery_directory -force -recurse –verbose

Schließlich installiert der Bereitstellungstask und startet den Dienst:

exec { & $executable install start }

Wenn Sie den Dienst bereitstellen, sollten Sie darauf achten, dass Ihre Implementierung von IsDevelopment false ausgibt. Ansonsten erhalten Sie einen Fehler Access Denied, wenn der Dateiserver den statische Ordner nicht findet. Es kann außerdem manchmal problematisch sein, den Dienst bei jeder Bereitstellung neu zu installieren. Eine andere Taktik besteht darin, anzuhalten und dann den Dienst zu starten, wenn er bereits installiert ist.

Wie Sie sehen, ist die Bereitstellung ganz einfach. IIS und InstallUtil fallen komplett aus der Gleichung; es gibt einen Bereitstellungsprozess, nicht zwei; und man muss sich keine Sorgen darüber machen, wie das Web und die Dienstschicht kommunizieren. Dieser Bereitstellungstask lässt sich während der Entwicklung der einheitlichen Web- und Dienstanwendung wiederholt ausführen!

Vorschau

Die beste Möglichkeit herauszufinden, ob sich dieses kombinierte Modell für Ihre Zwecke eignet, ist ein Projekt mit niedrigem Risiko zu finden und es auszuprobieren. Es ist so einfach, Anwendung mit dieser Architektur zu entwickeln und bereitzustellen. Es wird die gelegentliche Lernkurve geben (wenn Sie beispielsweise Nancy für MVC einsetzen). Doch das Großartige beim Einsatz von OWIN ist – selbst wenn der kombinierte Ansatz nicht funktioniert –, dass Sie immer noch die OWIN-Pipeline mithilfe des ASP.NET-Hosts (Microsoft.Owin.Host.SystemWeb) in IIS hosten können. Probieren Sie es aus und machen Sie Ihre eigenen Erfahrungen.

Wes McClure nutzt sein Fachwissen und hilft Klienten, schnell hochwertige Software zu liefern und exponentiell den Mehrwert zu steigern, den sie für Kunden schaffen. Er spricht gerne über alle, was mit Softwareentwicklung zu tun hat, ist Pluralsight-Autor und schreibt über seine Erfahrungen auf devblog.wesmcclure.com. Sie erreichen Ihn unter wes.mcclure@gmail.com.

Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: Howard Dierking (Microsoft), Damian Hickey, Chris Patterson (RelayHealth), Chris Ross (Microsoft) und Travis Smith
Howard Dierking ist Program Manager im Windows Azure Frameworks- und Tools-Team, wo er mit Schwerpunkt ASP.NET, NuGet und Web APIs tätig ist. Vorher arbeitete er als Chefredakteur des MSDN Magazine und leitete auch das Entwicklerzertifizierungsprogramm für Microsoft Learning. Vor seiner Zeit bei Microsoft arbeitete er zehn Jahre als Entwickler und Anwendungsarchitekt mit dem Schwerpunkt auf verteilte Systeme.

Chris Ross ist ein Software Design Engineer bei Microsoft und mit allem rund um Netzwerke und OWIN betraut.

Chris Patterson ist ein Architekt für RelayHealth, der Connectivity-Sparte der McKesson Corporation, und dort für die Architektur und Entwicklung von Anwendungen und Diensten verantwortlich, die die Pflegebereitstellung verbessern, indem sie Patienten, Gesundheitsdienstleister, Apotheken und Finanzinstitute verbinden. Chris hat wichtige Beiträge zu Topshelf und MassTransit geleistet und erhielt von Microsoft die Auszeichnung Most Valuable Professional für seine technischen Beiträge zur Community.

Damian Hickes ist ein Softwareentwickler mit Schwerpunkt auf DDD\CQRS\ES-basierten Anwendungen. Er ist ein Fürsprecher für .NET Open Source Software und arbeitet bei verschiedenen Projekten wie Nancy, NEventStore und anderen mit. Gelegentlich spricht er, falls ihm jemand zuhört, und ab und zu bloggt er unter http://dhickey.ie. Sie erreichen Ihn unter dhickey@gmail.com / @randompunter

Travis Smith ist ein Entwickler für Atlassian und den Atlassian Marketplace. Er verbreitet die Ideen eines offenen Webs, der Mehrsprachigkeit und sich entwickelnder Webtechnologien. Travis arbeitet an einer Reihe von Open-Source-Projekten mit, darunter Topshelf und MassTransit. Man trifft ihn auf Veranstaltungen für Entwickler, wo er leidenschaftlich über die Herstellung großartiger Software spricht; und im Internet auf http://travisthetechie.com.