Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

Edit: Les modèles d’hébergement de Web Api et SignalR

Poster un commentaire

Edit: j’ai ajouté OwinHost à la version précédente de l’article ainsi que les cas du service Windows.

 

Pour reprendre la terminologie WCF, on parle de self-hosting au sujet d’une application qui n’est pas hébergée par IIS, mais par un autre processus.

Web API et SignalR font partie de ces applications agnostiques quant au choix de leur hôte. Cet article a pour objet de monter comment mettre en œuvre concrètement l’hébergement de Web API dans 5 environnements différents:

  1. IIS
  2. Application Console
  3. Azure Worker Role
  4. OwinHost.exe
  5. Service Windows

 

Le déploiement de SignalR est strictement identique.

Hébergement IIS

Nous partons d’un projet MVC

30-03-2014 19-24-07

On complète avec le modèle Web API:

30-03-2014 19-25-45

Ce modèle va créer le fichier ~\App_Start\WebApiConfig qui déclare une route pour Web Api:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

On va compléter notre projet par un contrôleur Web Api sans doute pas très utile, mais qui montre la fonctionnalité:

 

public class CoucouController:ApiController
{
    public string Get()
    {
        return "Je suis la boite à coucou!";
    }
}

 

Si vous vous souvenez de la route il suffit de lancer cette url:

http//localhost:4567/api/Coucou

 

Pour récupérer le fichier:

30-03-2014 20-19-19

 

 Hébergement dans une application console

  • Commencez par créer une application console ordinaire.
  • Ajouter les classes Startup et CoucouController précédentes.

public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
"Default",
"{controller}/{id}",
new { id = RouteParameter.Optional });

app.UseWebApi(config);
}
}

  • On installe le package Nuget: Microsoft ASP.NET Web Api 2.1 Self Host

30-03-2014 20-28-35

 

 

30-03-2014 23-41-42

  • Une fois ajoutées les dépendances, il faut configurer un mini serveur.
class Program
{

static void Main(string[] args)
{
using (WebApp.Start<Startup>("http://localhost:15000"))
{
   Console.WriteLine("En attente");
   Console.ReadLine();
}
}

Notre serveur Web Api va répondre sur le port 15000 ce qu’indique la première ligne. Si tout se passe bien:

30-03-2014 20-48-47

Lancez un navigateur, par exemple Chrome et testez:

30-03-2014 20-51-23

Pas vraiment de difficultés là aussi.

Comme vous le voyez, par défaut IE requête en Json tandis que Chrome (et Firefox) réclament du XML.

Important

Notez tout de même un détail, pour tester ce code vous devrez le lancer en mode administrateur afin que le port puisse être ouvert correctement.

Vous pouvez aussi configurer le port avec netsh.exe:

netsh http add urlacl url=http://+:15000/ user=[machine]\[username]

 

Cette commande ajoute une réservation d’url pour l’url précisée et l’espace de noms donné:

user = user=[machine]\[username]

ou

user = user=[domain]\[username]

 

Hébergement dans un Azure Worker Role

 

La procédure est en réalité identique à celle de l’application console, c’est l’emplacement du code qui est différent. Notez également qu’un Worker Role diffère pour l’essentiel d’un Web Role parce qu’il n’a pas IIS installé.

Commençons par nous créer une application Azure:

30-03-2014 22-34-33

On ajoute un Worker Role:

30-03-2014 22-37-11

Avec Nuget on rajoute les dépendances suivantes à notre Worker Role:

30-03-2014 20-28-35

Les dépendances OWIN au Worker Role:

30-03-2014 22-59-14

Ainsi que les dépendances aux méthodes d’extension IAppBuilder:

30-03-2014 23-15-26

L’hôte OWIN:

30-03-2014 23-21-36

Et pour finir le serveur Http:

30-03-2014 23-41-42

 

L’étape suivante consiste à déclarer les points de terminaison Http afin que le service soit accessible depuis l’extérieur une fois déployé sur Azure. On ouvre le projet de configuration et on choisit le rôle précédemment ajouté:

30-03-2014 22-43-55

On ajoute un point de terminaison:

30-03-2014 22-46-25

Le port privé est 80, le port public 15000. Mais ces deux valeurs pourraient être identiques. Le port public est le port que verra le client lorsqu’il émettra une requête vers le service.

 

On complète ensuite le projet avec la classe Startup contenant la méthode suivante:


public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
"Default",
"{controller}/{id}",
new { id = RouteParameter.Optional });

app.UseWebApi(config);
}

 

UseWebApi est une méthode d’extension qui ajoute la route Web Api précisée au pipeline OWIN.

Cette fois on n’a pas ajouté /api dans la route. Dans ce genre de projet il peut probable d’avoir besoin d’autres routes et donc cela ne devrait pas poser de problèmes.

Note:

La classe doit absolument s’appeler Startup et la méthode Configuration et accepter comme paramètre IAppBuilder.

 

On ajoute ensuite notre contrôleur bien connu CoucouController vu précédemment.

On doit ensuite démarrer l’hôte OWIN dans la classe WorkerRole:


private IDisposable _app = null;

public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;

var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Endpoint1"];
string baseUri = string.Format("{0}://{1}", endpoint.Protocol, endpoint.IPEndpoint);

_app = WebApp.Start<Startup>(new StartOptions(url: baseUri));

return base.OnStart();
}

public override void OnStop()
{
if (_app != null)
{
_app.Dispose();
}
base.OnStop();
}

 

WebbApp.Start lance un hôte OWIN. On lui passe en paramètre le nom de la classe qui contient la méthode chargée d’initialiser le pipeline OWIN (Startup). Par convention il lance une méthode appelée Configure.

On peut tester le projet depuis l’émulateur en faisant F5.

Note:
Il se peut que vous receviez le message suivant:

System.MissingMemberException was unhandled by user code
  HResult=-2146233070
  Message=The server factory could not be located for the given input: Microsoft.Owin.Host.HttpListener
  Source=Microsoft.Owin.Hosting

 

C’est parce que HttpListener n’a pas été installé et donc que vous avez oublié une des étapes Nuget précédentes.

 

L’émulateur de calculs va assigner une adresse IP à notre service que nous allons récupérer:

30-03-2014 23-47-11

On a juste à faire un test depuis un navigateur comme avant:

30-03-2014 23-49-49

On constate que cette fois aussi tout fonctionne.

 Hébergement par OwinHost.exe

OwinHost.exe est une application console très légère spécialisée dans l’hébergement d’applications OWIN.

 

Il faut commencer par installer OwinHost.exe sur le serveur. La meilleure option est d’utiliser Chocolatey (https://chocolatey.org). C’est un gestionnaire de packages Nuget, mais contrairement à Nuget il ne déploie pas des librairies, mais des applications.

La commande pour installer Chocolatey est donnée dès la page d’accueil:

@powershell -NoProfile -ExecutionPolicy unrestricted -Command « iex ((new-object net.webclient).DownloadString(‘https://chocolatey.org/install.ps1&rsquo;)) » && SET PATH=%PATH%;%systemdrive%\chocolatey\bin

Normalement vous avez déjà Powershell, vous avez juste à la lancer depuis la ligne de commande.

On lance ensuite la commande depuis n’importe où:

cinst OwinHost

Elle installe OwinHost qui servira d’hôte et de serveur.

 

Ceci étant fait, laissons parler le code.

  • Lancez Visual Studio et créez un projet de librairie.
  • avec Nuget installer le package Owin
    install-package owin
  • Installez aussi le package Microsoft.AspNet.WebApi.Owin
  • Supprimer Class1 et créez la classe Startup

 

</pre>
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
"Default",
"{controller}");

app.UseWebApi(config);
}
}
  • compiler le projet et déployez le dans le répertoire c:\bin (attention au nom qui est obligatoire)
  • Aller dans c:\bin
  • lancer Owinhost depuis la ligne de commande

02-04-2014 01-46-50

Plusieurs points importants:

  • le numéro de port, mais aussi quelle application Owin lancer est paramétrable dans la ligne de commande ou bien un fichier de configuration
  • la librairie est attendue par OwinHost dans un répertoire /bin, par exemple c:\bin

 

Il ne reste plus qu’à tester depuis un navigateur Web.

Important: en fait j’ai un peu triché car actuellement ce code ne marche pas du probablement à un bug dans Web Api. Il marche très bien avec SignalR par exemple ou tout autre middleware.

Service Windows

  • On créée un projet Windows Service
  • On ajoute une classe Installer:

06-04-2014 10-39-08

  • On paramètre le ProcessInstaller et le ServiceInstaller
  • On ajoute une dépendance à Web Api et owin host ainsi qu’un listener:

06-04-2014 10-09-28

06-04-2014 10-27-57

30-03-2014 23-41-42

  • On ajoute le contrôleur CoucouController
  • On ajoute la classe Startup:

public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
"Default",
"{controller}/{id}",
new { id = RouteParameter.Optional });

app.UseWebApi(config);
}
}

  • Dans la classe d’initialisation du service on ajoute:

private IDisposable _app = null;

protected override void OnStart(string[] args)
{
_app = WebApp.Start<Startup>(new StartOptions("http://localhost:15000"));
}

protected override void OnStop()
{
_app.Dispose();
}

  • On compile et lance le service avec ce petit script lancé en mode administrateur:

%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\InstallUtil /i MONSERVICE.exe
sc start MONSERVICE

 

On vérifie avec un navigateur que tout fonctionne.

 

Pour désinstaller le service:

sc stop MONSERVICE

%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\InstallUtil /u MONSERVICE.exe

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s