[WCF] Prendre la main sur les protocoles
De base, WCF fournit toute l’infrastructure pour monter des solutions de services multiprotocoles. On peut fournir et consommer des services sur des carneaux divers et variés. Avant .net 4, fournir un même service pour deux Binding différents imposait une configuration très verbeuse (peut-être un peu trop). Après .net 4, et l’introduction des configurations à défaut, la configuration est devenue beaucoup plus facile.
Pour rappel: la configuration à défaut consiste à introduire des nœuds de configuration WCF (binding, beavior,.. etc…) sans propriété name ou alors avec la propriété name=””.
Seul petit hic, tous les développeurs n’ont pas forcément saisi que la pierre angulaire de tout cela résidait dans le mapping des protocoles. Sans ce mapping, WCF ne peut pas savoir que vous voulez utiliser tel ou tel type de Binding.
Avant toute configuration, si vous souhaitez utiliser les configurations à défaut il faut donc fixer le Binding utiliser pour chaque protocole.
La MSDN nous donne un exemple simple de configuration (https://msdn.microsoft.com/en-us/library/ee816881(v=vs.110).aspx)
<protocolMapping>
<add scheme="http" binding="basicHttpBinding"/>
<add scheme="net.tcp" binding="netTcpBinding"/>
<add scheme="net.pipe" binding="netNamedPipeBinding"/>
<add scheme="net.msmq" binding="netMsmqBinding"/>
</protocolMapping>
Cet exemple est simple, et s’utile pour les cas les plus faciles. Dans la pratique, dès que l’on veut mixer http et https, les choses sont un peu plus complexes.
Par exemple, la configuration suivante n’est pas possible :
<protocolMapping>
<clear/>
<!-- Binding utilisé par le HTTPS -->
<add scheme="https" binding="webHttpBinding"/>
<!-- Binding utilisé par le HTTP -->
<add scheme="http" binding="webHttpBinding"/>
</protocolMapping>
Pourquoi?
La réponse se trouve dans les configurations des Binding. On ne peut pas avoir un deux configurations de Binding à défaut pour un même type de Binding. Ceci est tout à fait normal, comment le system peut savoir quelle configuration utiliser, si aucune n’a de nom? Dans ce genre de situation, j’ai souvent vu des développeurs choisir d’utiliser un type de Binding pour HTTP et un autre type pour HTTPS ou alors coder leur propre type de Binding.
Heureusement, WCF est bien plus simple qu’il n’y parait, et il suffit de donner un nom à ses différentes configurations. Les noms peuvent ensuite être affectés comme bindingConfiguration de chaque protocole.
Ce qui donne au final ceci :
<system.serviceModel>
<protocolMapping>
<clear/>
<add scheme="https" binding="webHttpBinding" bindingConfiguration="httpsConfiguration"/>
<add scheme="http" binding="webHttpBinding" bindingConfiguration="httpConfiguration"/>
</protocolMapping>
<bindings>
<webHttpBinding>
<clear/>
<binding name="httpsConfiguration">
<security mode="Transport"/>
</binding>
<binding name="httpConfiguration">
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<clear/>
<behavior>
<!-- Suppression de meta-->
<serviceMetadata httpsGetEnabled="false" httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<clear/>
<behavior>
<!-- Configuration REST -->
<webHttp defaultBodyStyle="Bare" defaultOutgoingResponseFormat="Json"/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Facile non?