Partager via


ASP.NET

Débuter avec le projet Katana

Howard Dierking

L'époque n'était pas la même lors de la première publication d'ASP.NET, en 2002. L'Internet était encore relativement nouveau, avec approximativement 569 millions d'utilisateurs passant en moyenne 46 minutes par jour sur environ 3 millions de sites Web. Ces mêmes données relevées tout juste 10 ans plus tard révèlent un Internet d'environ 2,27 milliards d'utilisateurs passant en moyenne 4 heures par jour sur 555 millions de sites Web (voir bit.ly/MY7GzO).

Cette croissance a clairement encouragé des changements connexes dans les besoins des développeurs d'applications au niveau des infrastructures sous-jacentes, outils et runtimes qu'ils utilisent pour développer et exécuter des applications Web. Les applications Web modernes doivent être en mesure d'évoluer rapidement, en tirant profit de nombreuses infrastructures et de divers composants différents. Elles ont de plus besoin d'un faible encombrement afin de s'exécuter efficacement dans le runtime à grande échelle du cloud.

La motivation clé derrière le projet Katana consiste à s'assurer qu'ASP.NET peut satisfaire ces besoins actuels et futurs.

Qu'est-ce que Katana ?

Les germes du projet Katana ont en réalité été semés en dehors de Microsoft avec un projet open source intitulé l'Open Web Inter­face pour .NET (OWIN), une spécification qui définit les interactions entre serveurs Web et composants d'application (voir owin.org). Du fait que l'objectif de la spécification vise à stimuler un écosystème large et dynamique de composants d'applications et serveurs Web basés sur Microsoft .NET Framework, toutes les interactions entre serveurs et applications sont réduites à un petit ensemble de types et une signature de la fonction unique connue sous le nom de déléguée d'application, ou AppFunc :

using AppFunc = Func<IDictionary<string, object>, Task>;

Chaque composant d'une application basée sur OWIN fournit un délégué d'application à un serveur. Les composants sont ensuite chaînés dans un pipeline au sein duquel un serveur basé sur OWIN pousse des demandes. Afin d'utiliser efficacement des ressources, tous les composants du pipeline doivent être asynchrones, et cela se reflète dans le délégué d'application renvoyant un objet Task.

Tous les états, y compris l'état de l'application, l'état de la demande, l'état du serveur, et d'autres, sont inclus dans l'objet IDictionary spécifié sur le délégué d'application. Cette structure de données, connue comme le dictionnaire d'environnement, est passée de composant en composant à mesure que la demande avance dans le pipeline. Si n'importe quelle donnée de clé/valeur peut être insérée dans le dictionnaire d'environnement, la spécification OWIN définit des clés pour certains éléments centraux de HTTP, comme illustré sur la figure 1.

Figure 1 Clés de dictionnaire d'environnement requises pour une demande HTTP

 

Nom de clé Description de valeur
« owin.RequestBody » Un flux avec le corps de la demande, le cas échéant. Stream.Null peut être utilisé comme espace réservé s'il n'y a pas de corps de la demande.
« owin.RequestHeaders » Un IDictionary d'en-tête de demande.
« owin.RequestMethod » Une chaîne contenant la méthode de demande HTTP de la demande (par exemple, GET et POST).
« owin.RequestPath » Une chaîne contenant le chemin d'accès à la demande. Le chemin doit se rapporter à la « racine » du délégué d'application.
« owin.RequestPathBase » Une chaîne contenant la partie du chemin d'accès à la demande correspondant à la « racine » du délégué d'application.
« owin.RequestProtocol » Une chaîne contenant la version et le nom du protocole (par exemple, HTTP/1.0 ou HTTP/1.1).
« owin.RequestQueryString » Une chaîne contenant le composant de chaîne de demande de l'URI de demande HTTP, sans « ? » de début (par exemple, foo=bar&baz=quux). La valeur peut être une chaîne vide.
« owin.RequestScheme » Une chaîne contenant le modèle URI utilisé pour la demande (par exemple, HTTP ou HTTPS).

La définition d'un ensemble de base de paires clé-valeur de dictionnaire d'environnement permet à de nombreux auteurs différents d'infrastructures et de composants d'interagir dans un pipeline OWIN, sans forcer l'accord sur un modèle d'objet .NET spécifique, tel que ceux de HttpContextBase dans ASP.NET MVC ou HttpRequestMessage/HttpResponseMessage dans une API Web ASP.NET.

Ces deux éléments, le délégué d'application et le dictionnaire d'environnement, constituent la spécification OWIN. Le projet Katana correspond à l'ensemble d'infrastructures et de composants basés sur OWIN créés et expédiés par Microsoft.

Vous pouvez voir des composants Katana dans la pile architecturale illustrée à la figure 2.

Figure 2 Architecture du projet Katana

La pile est constituée des couches suivantes :

  • Hôte : le processus qui exécute l'application. Il peut s'agir de n'importe quel élément depuis IIS ou un exécutable autonome, jusqu'à votre propre programme personnalisé. L'hôte est responsable du démarrage, du chargement d'autres composants OWIN et d'une mise à l'arrêt sans encombre.
  • Serveur : responsable de la liaison avec un port TCP, de la constitution du dictionnaire d'environnement et du traitement de demandes au sein d'un pipeline OWIN.
  • Middleware : le nom donné à tous les composants qui traitent des demandes dans un pipeline OWIN. Cela va d'un simple composant de compression à une infrastructure complète telle qu'une API Web ASP.NET, même si, du point de vue du serveur, il s'agit simplement d'un composant qui expose le délégué d'application.
  • Application : il s'agit de votre code. Du fait que Katana ne vient pas remplacer ASP.NET mais est plutôt une nouvelle manière de composer et d'héberger des composants, les applications SignalR et API Web ASP.NET existantes demeurent inchangées, car ces infrastructures peuvent prendre part à un pipeline OWIN. En réalité, pour ces types d'applications, les composants Katana seront visibles uniquement dans une petite classe de configuration.

D'un point de vue architectural, Katana est conçu de telle manière que chacune de ces couches puissent être facilement remplacée, souvent sans devoir régénérer le code. Lors du traitement d'une demande HTTP, les couches travaillent ensemble d'une manière similaire au flux de données présenté à la figure 3.

Figure 3 Exemple du flux de données dans Katana

Création d'une application Web moderne avec Katana

Généralement, les applications Web modernes ont quatre fonctionnalités :

  1. Génération de balises côté serveur
  2. Envoi de fichier statique
  3. API Web pour gestion des demandes AJAX
  4. Messagerie en temps réel

Le développement d'une application avec toutes ces fonctionnalités nécessite un ensemble de différentes infrastructures spécialisées de manière adéquate pour la fonctionnalité concernée. Néanmoins, la composition d'une application à partir de telles infrastructures peut être un défi et nécessite actuellement l'hébergement des différents composants d'application sur IIS, en les isolant éventuellement entre eux à l'aide d'applications et de répertoires virtuels.

En revanche, Katana vous permet de composer une application Web moderne à partir d'une large gamme de technologies Web différentes, puis d'héberger cette application où vous le souhaitez, exposée sous un point de terminaison HTTP unique. Cela présente plusieurs avantages :

  • Le déploiement est simple parce qu'il implique seulement une application uniquement et non une application par fonctionnalité.
  • Vous pouvez ajouter des fonctionnalités, telles que l'authentification, qui peut s'appliquer à tous les composants en aval dans le pipeline.
  • Différents composants, qu'il s'agisse de Microsoft ou de tiers, peuvent fonctionner sur le même état de la demande via le dictionnaire d'environnement.

Je vais à présent explorer un exemple d'application associé à un domaine que vous devriez connaître : le suivi des bogues. L'application présentera un ensemble de bogues dans différents états (journal des travaux en souffrance, mode actif et terminé) et me permet de déplacer le bogue entre les états. En outre, du fait qu'un grand nombre d'individus différents pourraient gérer les bogues simultanément, tous les navigateurs seront mis à jour en temps réel lorsque l'état d'un bogue change. Voici ce que je vais utiliser pour développer l'application : Nancy (nancyfx.org) pour la génération de balises côté serveur et l'envoi de fichier statique, API Web ASP.NET (asp.net/web-api) pour la gestion de demandes AJAX et SignalR (signalr.net) pour les services de messagerie en temps réel.

De plus, du fait que je ne vais pas consacrer beaucoup de temps aux balises et scripts pour le client navigateur, je vais utiliser Knockout.js pour séparer la balise HTML de l'API Web et des données SignalR.

Le principe fondamental à conserver à l'esprit est que je pars de toutes ces différentes infrastructures vers un pipeline OWIN unique, afin que de nouvelles fonctionnalités deviennent disponibles lorsque je les ajoute à l'application en les insérant simplement dans le pipeline.

Mise en route

Un des objectifs de Katana vise à vous fournir un contrôle précis des fonctionnalités ajoutées à votre application (et, par conséquent, de vos dépenses en termes de performances pour le traitement de chaque demande). En conservant cela à l'esprit, je commence par créer un nouveau projet d'application Web ASP.NET vide dans Visual Studio 2013 Preview, comme illustré à la figure 4.

Figure 4 Un nouveau projet d'application Web ASP.NET dans Visual Studio 2013 Preview

Des modèles de projet Web, même vides, fournissent une fonctionnalité utile en cela que, par défaut, ils placent des assemblies compilés directement dans le dossier /bin au lieu du dossier /bin/debug (comme c'est courant dans d'autres types de projets). Le Katana par défaut cherche des assemblies dans ce dossier /bin. Vous pourriez créer une application basée sur Katana comme une bibliothèque de classes, mais vous devez ou bien modifier les propriétés de votre projet pour vous conformer à cette structure, ou bien fournir votre propre chargeur d'application personnalisé capable de chercher des assemblies et des types dans une structure de dossiers différente.

Je développe ensuite le code de génération de balises côté ­serveur en utilisant l'infrastructure Web Nancy.

Nancy a une syntaxe laconique, ce qui permet de développer rapidement des services et des sites basés sur HTTP. Le plus important pour cet exercice est que, comme l'API Web ASP.NET, il ne développe aucune dépendance vis à vis du System.Web.dll et il est conçu pour s'exécuter dans un pipeline OWIN. Des infrastructures telles qu'ASP.NET MVC ont des dépendances vis à vis du System.Web.dll (au moment de son écriture), ce qui les rend moins idéales pour des scénarios d'hébergement non-IIS.

En grande majorité, lorsque vous ajoutez une nouvelle fonctionnalité à l'application, vous commencez par ajouter un package NuGet. (Vous pouvez consulter davantage d'informations sur NuGet à l'emplacement suivant : docs.nuget.org.) Au moment de la rédaction de cet article, nombre des packages utilisés ici sont des versions préliminaires afin de s'assurer d'autoriser des versions préliminaires de packages devant être affichées dans la boîte de dialogue NuGet.

Pour ajouter Nancy à l'application, je pourrais simplement installer le package NuGet Nancy. Néanmoins, du fait que je veux aussi exécuter Nancy dans un pipeline OWIN, je vais installer le package Nancy.Owin (nuget.org/packages/nancy.owin). Cela installera le package Nancy en tant que dépendance et fournira des méthodes d'assistance supplémentaires pour la configuration de Nancy dans mon pipeline OWIN.

Je dois ensuite créer un module Nancy (similaire à un contrôleur Model-­View-Controller, ou MVC) pour gérer des demandes, ainsi qu'une vue pour afficher quelque chose dans le navigateur. Voici le code pour le module (HomeModule.cs) : 

public class HomeModule : NancyModule
{
  public HomeModule() {
    Get["/"] = _ => {
      var model = new { title = "We've Got Issues..." };
      return View["home", model];
    };
  }
}

Comme vous pouvez le voir, le module déclare que des demandes adressées à la racine de l'application (« / ») devraient être gérées par le délégué anonyme défini dans le lambda associé. Cette fonction créée un modèle contenant le titre de la page et indique à Nancy de rendre la vue « accueil », en passant le modèle à la vue. La vue, illustrée à la figure 5, insère la propriété du titre du modèle à la fois dans le titre de la page et dans les éléments h1.

Figure 5 Accueil.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>@Model.title</title>
</head>
  <body>
    <header>
      <h1>@Model.title</h1>   
    </header>
    <section>
      <h2>Backlog</h2>
      <ul class="bugs" id="backlog">
        <li>a bug</li>
      </ul>
    </section>
    <section>
      <h2>Working</h2>
      <ul class="bugs" id="working">
        <li>a bug</li>
      </ul>
    </section>
    <section>
      <h2>Done</h2>
      <ul class="bugs" id="done">
        <li>a bug</li>
      </ul>
    </section>
  </body>
</html>

Pour plus d'informations sur ces listes, consultez la documentation Nancy.

Maintenant que j'ai implémenté la fonctionnalité Nancy de base, je dois établir un pipeline OWIN et configurer le module Nancy pour prendre part à ce pipeline. Pour cela, je dois tout d'abord installer l'hôte Katana et les composants du serveur, puis écrire un petit volume de code de base pour configurer le pipeline OWIN et insérer Nancy dans ce pipeline.

Pour l'hôte Katana et les composants du serveur, je vais commencer par utiliser IIS Express et System.Web. En effet, ils sont par nature compris par Visual Studio et permettront une expérience F5 homogène tout en développant l'application. Pour intégrer l'hôte System.Web dans le projet, j'installe NuGet package Microsoft.Owin.Host.SystemWeb (bit.ly/19EZ2Rw).

Les composants Katana par défaut utilisent plusieurs conventions différentes permettant de charger et d'exécuter des applications OWIN, dont la classe de démarrage. Lorsqu'un hôte Katana charge une application OWIN, il découvre et exécute une classe de démarrage basée sur les règles suivantes (par ordre de priorité) :

  • Si le fichier web.config contient un appSetting avec clé=« owin:AppStartup », le chargeur utilise la valeur de paramètre. Cette valeur doit être un nom de type .NET valide.
  • Si l'assembly contient l'attribut [assembly: OwinStartup(typeof(MyStartup))], le chargeur utilisera le type spécifié dans la valeur d'attribut.
  • Si aucune de ces conditions n'est vraie, le chargeur analyse les assemblies chargés, à la recherche d'un type nommé Startup avec une méthode qui correspond à l'annulation de signature Configure(IAppBuilder app).

Pour cet exemple, je vais permettre au chargeur d'analyser des assemblies pour la classe. Néanmoins, si vous avez plusieurs types et assemblies différents dans votre projet, il serait sage d'utiliser soit l'appSetting, soit l'attribut assembly pour empêcher toute analyse inutile.

Je vais créer la classe de démarrage qui analysera mon pipeline OWIN et ajoutera Nancy comme composant de pipeline. Je crée une nouvelle classe intitulée Startup et j'ajoute une méthode de configuration comme suit :

public class Startup
{
  public void Configuration(IAppBuilder app)
  {
    app.UseNancy();
  }
}

UseNancy est une méthode d'extension mise à disposition par le package NuGet Nancy.Owin. Si vous pouvez ajouter un middleware en utilisant les méthodes Use plus génériques de l'IAppBuilder, de nombreuses bibliothèques de middleware fourniront ces méthodes d'extension utiles qui facilitent le processus de configuration.

À ce stade, vous pouvez exécuter le projet dans Visual Studio en utilisant F5 et voir que même si ça n'est pas passionnant encore, vous disposez d'une application Web entièrement fonctionnelle. Le pipeline OWIN compte alors un composant unique, Nancy, comme illustré à la Figure 6.

A Functional Web Application with a Single Component
Figure 6 Une application Web fonctionnelle avec un composant unique

Intégration de données avec API Web ASP.NET

Actuellement, la vue HTML se compose de balisage statique principal. Je vais à présent donner aux utilisateurs des bogues véritables sur lesquels travailler. Pour de nombreuses applications Web modernes, la tâche de fourniture de données au client navigateur est passée de l'infrastructure de génération de marquage côté serveur (comme le module Nancy) à un service API Web distinct. Le navigateur charge ensuite la page HTML et exécute immédiatement JavaScript, ce qui extrait les données de l'API Web et développe de manière dynamique du balisage HTML dans la page elle-même.

Je vais commencer par construire l'API Web en utilisant l'infrastructure API Web ASP.NET. Comme d'habitude, la première étape consiste à installer le package NuGet API Web. Afin de m'assurer de pouvoir insérer facilement l'API Web ASP.NET dans mon propre pipeline OWIN, je vais installer le package Microsoft.Asp­Net.WebApi.Owin (bit.ly/1dnocmK). Ce package va installer le reste de l'infrastructure API Web ASP.NET en tant que dépendances. Après avoir installé l'infrastructure, je crée une API simple, comme illustré à la figure 7.

Figure 7 BugsController.cs

public class BugsController : ApiController
{
  IBugsRepository _bugsRepository = new BugsRepository();
  public IEnumerable<Bug> Get()
  {
    return _bugsRepository.GetBugs();
  }
  [HttpPost("api/bugs/backlog")]
  public Bug MoveToBacklog([FromBody] int id)
  {
    var bug = _bugsRepository.GetBugs().First(b=>b.id==id);
    bug.state = "backlog";
    return bug;
  }
  [HttpPost("api/bugs/working")]
  public Bug MoveToWorking([FromBody] int id)
  {
    var bug = _bugsRepository.GetBugs().First(b => b.id == id);
    bug.state = "working";
    return bug;
  }
  [HttpPost("api/bugs/done")]
  public Bug MoveToDone([FromBody] int id)
  {
    var bug = _bugsRepository.GetBugs().First(b => b.id == id);
    bug.state = "done";
    return bug;
  }
}

L'API contient une méthode pour retourner un ensemble d'objets bug à partir d'un référentiel, ainsi que certaines méthodes pour déplacer des bogues entre différents états. Vous trouverez de bien plus amples informations sur l'API Web ASP.NET à l'emplacement suivant : asp.net/web-api.

À présent que j'ai un contrôleur API Web ASP.NET défini, j'ai besoin de l'ajouter à mon pipeline OWIN existant. Pour cela, il me suffit d'ajouter les lignes suivantes à la méthode Configuration dans ma classe de démarrage :

var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute("bugs", "api/{Controller}");
app.UseWebApi(config);

De la même manière que Nancy, le package OWIN API Web ASP.NET fournit la méthode d'extension UseWebApi, ce qui facilite l'intégration de l'API Web ASP.NET dans mon pipeline OWIN existant. Le pipeline OWIN compte à présent deux composants, API Web ASP.NET et Nancy, comme illustré à la figure 8.

The OWIN Pipeline with Two Components
Figure 8 Le Pipeline OWIN avec deux composants

À mesure que des demandes arrivent dans le pipeline, si elles correspondent à une des règles de routage API Web ASP.NET, l'API Web ASP.NET gère la demande et génère une réponse. Dans le cas contraire, la demande continue via le pipeline, où Nancy tente de la traiter. Si aucun composant de pipeline ne peut gérer une demande spécifique, les composants Katana par défaut renvoient une réponse HTTP 404.

Bien que je dispose d'une API Web ASP.NET qui fonctionne, la vue d'accueil n'y accède pas actuellement. J'ajoute par conséquent du code pour utiliser des données à partir de l'API Web et générer une liste de bogues dans chacun des différents états : journal des travaux en souffrance, mode actif et terminé. Pour cette tâche, je vais tirer profit de Knockout.js, une bibliothèque Model-View-ViewModel (MVVM) JavaScript. Vous trouverez plus d'information sur le masquage à l'adresse suivante : knockoutjs.com.

Pour activer une génération dynamique côté client de marquage HTML en utilisant Knockout, la première chose que je dois faire consiste à extraire tous les bogues de l'API Web ASP.NET et à créer un viewModel que Knockout peut lier à des éléments HTML. Ce processus est illustré à la figure 9.

Figure 9 Configuration du viewModel de bogues

<script>
  $(function () {
    var viewModel;
    $.getJSON('/api/bugs', function(data) {
      var model = data;
      viewModel = {
        backlog: ko.observableArray(
          model.filter(function(element) { return element.state === 'backlog'; })),
        working: ko.observableArray(
          model.filter(function(element) { return element.state === 'working'; })),
        done: ko.observableArray(
          model.filter(function(element) { return element.state === 'done'; })),
        changeState: function (bug, newState) {
          var self = this;
          $.post('/api/bugs/' + newState, { '': bug.id }, function(data){
            self.moveBug(data);
          });
        },
        moveBug: function (bug) {
          // Remove the item from one of the existing lists
          ...
          // Add bug to correct list
          this[bug.state].push(bug);
        }
      };
      ko.applyBindings(viewModel);
    })
  })
</script>

Une fois le viewModel créé, Knockout peut alors générer et mettre à jour de manière dynamique du contenu HTML en associant le viewModel à des éléments HTML décorés d'attributs spécifiques Knockout. Par exemple, la liste du journal des travaux en souffrance peut être générée à partir du viewModel en utilisant les attributs illustrés à la figure 10.

Figure 10 Attributs pour générer la liste du journal des travaux en souffrance

<section>
  <h2>Backlog</h2>
  <ul class="bugs" id="backlog" data-bind="foreach:backlog">
    <li>
      [<span data-bind="text: id"></span>] <span data-bind="text: title"></span>:
        <span data-bind="text: description"></span>
      <ul>
        <li><a href="#" data-bind="click: $root.changeState.bind($root, $data,
          'working')">Move to working</a></li>   
        <li><a href="#" data-bind="click: $root.changeState.bind($root, $data,
          'done')">Move to done</a></li>   
      </ul>
    </li>
  </ul>
</section>

Ajout de notifications de modification en temps réel avec SignalR

À ce stade, je dispose d'une application Web page unique entièrement fonctionnelle. Les utilisateurs peuvent accéder à la vue d'accueil et déplacer des bogues entre différents états de bogues. De plus, les technologies sous-jacentes pour le niveau actuel de fonctionnalité, Nancy et API Web ASP.NET, s'exécutent ensemble dans le même pipeline OWIN.

Je vais cependant aller un peu plus loin et autoriser différents utilisateurs à voir, en temps réel, les mises à jour apportées à des bogues par d'autres utilisateurs. Pour cela, je vais utiliser la bibliothèque SignalR, qui fournit à la fois une API client et serveur pour la gestion d'échanges de messages en temps réel entre le navigateur et un serveur Web. SignalR est également écrit pour s'exécuter dans un pipeline OWIN. Il ne sera donc pas très intéressant de l'ajouter à mon application existante.

Je vais utiliser une fonctionnalité de SignalR appelée concentrateurs, et, bien que les détails de SignalR s'éloignent du sujet de cet article, un concentrateur permet aux clients et serveurs d'appeler des méthodes l'une sur l'autre. (Vous trouverez une excellente présentation de SignalR à l'emplacement suivant : bit.ly/14WIx1t.) Dans mon application, lorsque l'API Web ASP.NET reçoit une demande pour modifier l'état d'un bogue, je mets à jour le bogue, puis je le diffuse mis à jour via le concentrateur SignalR à tous les clients navigateurs actuellement connectés à l'application.

Je vais démarrer ce processus en créant un concentrateur sur le serveur. Du fait que je ne profite d'aucune fonctionnalité SignalR supplémentaire, mon concentrateur se compose simplement de la définition de classe vide suivante :

[HubName("bugs")]
public class BugHub : Hub
{
}

Afin d'envoyer des diffusions au concentrateur à partir de l'API Web ASP.NET, je dois tout d'abord obtenir une instance dans son contexte d'exécution. Je peux le faire en ajoutant le constructeur BugsController suivant :

public BugsController()
{
  _hub = GlobalHost.ConnectionManager.GetHubContext<BugHub>();
}

Depuis une des actions MoveToXX, je peux ensuite diffuser le bogue mis à jour à tous les clients navigateurs connectés :

_hub.Clients.All.moved(bug);

Dans la vue d'accueil, après avoir ajouté quelques références de script aux bibliothèques JavaScript SignalR, je peux me connecter au bugsHub et commencer à écouter des messages « déplacés » avec ce qui suit :

$.connection.hub.logging = true;
var bugsHub = $.connection.bugs;
bugsHub.client.moved = function (item) {
  viewModel.moveBug(item);
};
$.connection.hub.start().done(function() {
  console.log('hub connection open');
});

Veuillez noter que lorsque je reçois un appel du serveur via la fonction déplacée, j'appelle la méthode moveBug viewModel de la même manière que je l'ai fait dans le gestionnaire à clic de l'élément. La différence repose sur le fait que du fait que cette méthode est le résultat d'une diffusion SignalR, tous les clients navigateurs peuvent mettre à jour leurs viewModels simultanément. Vous pouvez voir cela clairement en ouvrant deux fenêtres de navigateurs, en apportant des modifications dans l'une, puis en affichant le changement d'état dans l'autre.

Comme je l'ai fait remarquer, l'ajout de SignalR au pipeline OWIN n'est pas intéressant. J'ajoute simplement ce qui suit à la méthode Configuration de la classe de démarrage :

app.MapSignalR();

Cela crée un pipeline comme celui présenté à la figure 11.

The OWIN Pipeline with Three Components
Figure 11 Le pipeline OWIN avec trois composants

Passage à l'hébergement automatique

Je dispose à présent d'une application de gestion de bogues qui fonctionne et qui, même s'il lui manque quelques fonctionnalités clés, peut réaliser quelques tâches intéressantes. J'ai ajouté progressivement des fonctionnalités à l'application en utilisant à la fois des composants middleware Katana tiers et Microsoft. Néanmoins, la grande majorité de cela était déjà possible aujourd'hui en utilisant des HttpModules et HttpHandlers ASP.NET. Qu'ai-je donc véritablement accompli, en plus de fournir une approche plus simple, véhiculée par du code, pour composer des éléments de pipeline ?

La solution consiste à mémoriser le schéma d'architecture Katana haut niveau de la figure 2. Jusqu'à présent, j'ai juste travaillé sur les deux couches supérieures de la pile Katana. Néanmoins, toutes ces couches peuvent être facilement remplacées, y compris le serveur et l'hôte.

Pour en faire la démonstration, je prends tout mon pipeline, je l'extrais d'IIS et System.Web.dll, et je l'installe sur un serveur HTTP simple et léger qui est hébergé par un exécutable Katana appelé OwinHost.exe. L'hébergement automatique peut s'avérer utile dans divers cas de figure, allant de configurations où aucun serveur Web n'est installé sur la machine de développement, à des situations de production où l'application est déployée dans un environnement d'hébergement partagé qui utilise l'isolation des processus et n'expose pas l'accès à un serveur Web.

Je commence par installer les packages NuGet supplémentaires suivants :

Je régénère ensuite l'application. Veuillez noter qu'il n'est pas obligatoire de régénérer pour exécuter l'application sur un serveur et un hôte nouveaux. La seule exigence est que ces fichiers existent dans le dossier /bin au moment de l'exécution et la régénération est une manière pratique de copier les fichiers dans /bin.

Une fois les packages installés et les fichiers copiés, j'ouvre une invite de commande, j'accède au dossier racine du projet Web et, comme illustré à la figure 12, j'appelle OwinHost.exe depuis le dossier des packages :

> ..\packages\OwinHost.2.0.0\tools\OwinHost.exe

Calling OwinHost.exe from Within the Packages Folder
Figure 12 Appel d'OwinHost.exe depuis le dossier des packages

Par défaut, OwinHost.exe va se lancer, charger le serveur Microsoft.Ow­in.Host.HttpListener et commencer à écouter sur le port 5000. Je peux ensuite accéder à http://localhost:5000 pour confirmer que l'intégralité de l'application est en cours d'exécution.

De plus, presque tous les défauts peuvent être remplacés à l'aide de commutateurs de ligne de commande. Par exemple, si vous voulez écouter sur un autre port, indiquez -p 12345. Si vous voulez utiliser un tout autre serveur, utilisez -s your.custom.server.assembly. Toute la force de la conception de Katana repose sur sa modularité. À mesure que des innovations interviennent, sur toute couche de la pile, elles peuvent immédiatement être intégrées dans des applications en cours d'exécution. Et du fait que le contrat entre tous les composants de la pile est simplement le délégué d'application; le rythme d'innovation peut être bien supérieur à ce qui est actuellement disponible.

Les premiers pas de la mise en route

Katana 2.0 sera lancée avec Visual Studio 2013. La nouvelle version compte deux centres d'intérêt principaux :

  • Fourniture de l'infrastructure principale pour l'hébergement automatique
  • Fourniture d'un ensemble complet de middleware pour l'authentification, y compris des prestataires sociaux tels que Facebook, Google, Twitter et Compte Microsoft, ainsi que des prestataires pour Windows Azure Active Directory, cookies et fédération

Une fois Katana 2.0 lancée, le travail débute immédiatement sur l'ensemble suivant de composants Katana. Les détails et priorités sont encore en cours de détermination, mais vous pouvez influencer cette discussion en soumettant des problèmes à l'emplacement suivant : katanaproject.codeplex.com. Enfin, tout le code de cet article est disponible à l'emplacement suivant : bit.ly/1alOF4m.

Howard Dierking *est responsable de programme au sein de l'équipe Windows Azure Frameworks and Tools. Son travail est axé sur les API Web, NuGet et ASP.NET. Auparavant, Howard Dierking a occupé le poste de rédacteur en chef de MSDN Magazine. Il a également géré le programme de certification de développeurs pour Microsoft Learning. Avant Microsoft, il a travaillé 10 ans en tant que développeur et architecte d'applications spécialisé dans les systèmes distribués. *

Merci aux experts techniques Microsoft suivants d'avoir relu cet article : Brady Gaster et Scott Hanselman