A découvrir d'urgence : Ekioo, le blog de ma société

Affichage des articles dont le libellé est Binding. Afficher tous les articles
Affichage des articles dont le libellé est Binding. Afficher tous les articles

samedi 24 janvier 2009

WCF et IIS avec les sites web qui ont des identités multiples

Je profite du dernier post de Cyril Durand pour finaliser un petit article que j'avais entamé sans jamais vraiment le finir. Il concerne le problème du binding des services WFC sur un IIS qui gère plusieurs identités pour le même site web :

This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.
Parameter name: item


où pour les francophones :

Cette collection contient déjà une adresse avec le schéma http. Une adresse tout au plus par schéma est possible dans cette collection.
Nom du paramètre : item

Voici ce qui se passe lorsque vous avez un site web configuré avec plusieurs identités ( ex: www.siteweb.com et siteweb.com ) lorsque vous tentez d'accéder au fichier Service.svc de votre service WCF.

Pourquoi ? WCF ne supporte pas les identités multiples sur le même site. Comment faire dès lors pour résoudre cette épineuse situation ?

De nombreux blogs proposent des solutions, qui si elles ne résolvent pas réellement le problème, ont le mérite d'aider à comprendre comment tout cela fonctionne :

Sur developpez.net, un premier échanges m'a permit d'identifier que le problème venait effectivement des identités multiples. Les serveurs mutualisés qui n'y font pas attention sont les premiers touchés.

Une première solution est donnée par Rob Reynolds : Il faut dériver la classe ServiceHostFactory comme suit :

using System.ServiceModel;
using System.ServiceModel.Activation;

public class CustomServiceFactory : ServiceHostFactory
{

private int baseAddressIndex = 0;

protected override ServiceHost CreateServiceHost(System.Type serviceType, System.Uri[] baseAddresses)
{
return new ServiceHost(serviceType, baseAddresses[baseAddressIndex]);
}
}
Puis, dans le fichier *.svc :

<%@ ServiceHost Language="VB" Debug="true"
Service="Organization.Services.TempService"
Factory="Organization.Services.CustomServiceFactory" %>
Premier problème, comment connaitre l'indice de l'adresse qu'on souhaite utiliser ?
Deuxième problème, que se passe t'il si notre service WPF est instancié pour le nom de domaine www.siteweb.com une première fois (là ça marche) et qu'on tente d'y accéder ensuite via siteweb.com (là, ça marche plus).

L'idée n'était pourtant pas si mal et venait d'ici à l'origine.

Deux autres échanges ici et là m'ont finalement menés à une solution qui semblait prometteuse. Mais voila, la solution du filtre permet en pratique de faire fonctionner WCF avec une seule identité. Or, je ne souhaite pas choisir en www.siteweb.com et siteweb.com, je veux que la solution marche dans tout les cas !

Je n'ai pas testé la solution de Cyril qui semble avoir réussit à gérer les différentes identités en se passant du fichier de configuration WFC. Pour des raisons de performances, j'avais déjà décidé de laisser de coté les services WCF pour faire communiquer Silverlight avec mes services webs.

Actuellement, j'utilise une solution à base de javascript, de serialisation json en ayant implémenté quelques fonctions génériques qui simplifient bien la vie. Si j'ai un temps de temps, je décrirais cette méthode en détails dans un prochain article.

dimanche 14 décembre 2008

Binding en Silverlight 2.0

Avec WPF, Microsoft à introduit une nouvelle façon de lier des données aux contrôler par la syntaxe {Binding}. Cette syntaxe est très légère et incroyablement efficace lorsqu'on sait s'en servir. Vous pouvez consulter DataBinding Quick Reference pour faire un tour d'horizon de cette syntaxe.

Silverlight lui aussi permet de faire du binding de cette façon, mais de façon plus limité. Par exemple, le très utile ElementName, qui permet de cibler un autre contrôle par son nom, n'est pas disponible. En WPF, il suffit de faire comme le décrit Pascal Cabanel sur son blog.

Pourtant, avec Silverlight, c'est un peu plus complexe. La façon la plus simple est de passer par des évènements et de mettre à jour les DataContexte de chaque contrôle à chaque changement. Ca marche très bien, surtout si l'application n'est pas très complexe.

La solution qui est recommandée par Microsoft, je l'ai trouvé sur un ce webcast. Il faut créer une classe intermédiaire qui implémente INotifyPropertyChanged, un Controller, et qui va faire le lien entre tous les contrôles et sur lequel va reposer tout notre binding.