Les pièges de WCF en partial trust (shared hosting par exemple)
Je vous palais récemment des nouvelles possibilités offertes par Windows Server 2008 en matière d'hébergement de services WCF.
Ce qui peut être intéressant, c'est d'héberger un service WCF en hébergement mutualisé. Je suis en train d'en faire l'expérience, et si cela n'a rien d'impossible, il y a quand même quelques pièges pour l'instant très peu (voire pas) documentés.
Le principal souci vient du fait qu'en hébergement mutualisé, votre application va s'exécuter sous des conditions de sécurité restreintes. Dans la plupart des cas, ce sera en medium trust.
Première chose à savoir, WCF 1.0 (du Framework 3.0) ne supporte pas de s'exécuter en medium trust. Il peut s'exécuter qu'en Full Trust. Par contre, la version fournie avec .NET 3.5 (RTM à la fin du mois) peut désormais s'exécuter en medium trust.
Pour un hébergement mutualisé, c'est donc cette version que vous utiliserez. Ce post de Steve Maine indique les fonctionnalités disponibles en Medium Trust :
- BasicHttpBinding avec HTTP transport security
- WebHttpBinding
- Serialization avec XML Serializer
- Serialization avec DataContractSerializer
- RSS/Atom
J'ai suivi ces guidelines, et mon service utilise BasicHTTPBinding et le DataContractSerializer. Pourtant, lors de l'appel de certaines opérations sur mon service, mon client jette une CommunicationException qui n'est d'aucune aide, et ferme la connexion :
An error occurred while receiving the HTTP response to *myserver*. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
Ce qu'il se passe, c'est que le serveur a rencontré un problème lors de la sérialisation et a fermé la connexion. Coté serveur, aucune exception n'est lancée, il est donc impossible de savoir ce qu'il s'est passé.
Pour débugger ceci, je vous conseille de créer une page qui contient uniquement une opération de sérialisation avec le DataContractSerializer :
public static void Test(Player item)
{
DataContractSerializer ser = new DataContractSerializer(typeof(Player));
MemoryStream stream = new MemoryStream();
ser.WriteObject(stream, item);
stream.Close();
}
En affichant cette page, vous saurez peut être d'où vient le problème (l'exception s'affichera dans la page).
Dans mon cas le problème était que les attributs [DataMember] étaient placés sur des membres privés. Cela fonctionne en FullTrust (donc dans mon environnement de développement), mais pas en medium trust. Ce qui est logique, mais documenté nulle part. J'ai donc juste déplacé les attributs sur les propriétés get/set associées pour que cela fonctionne.
J'ai remplacé :
[DataContract]
public class PlayerInfo
{
[DataMember]
private long money;
[DataMember]
private long useableMoney;
public long Money
{
get { return money; }
set { money = value; }
}
public long UseableMoney
{
get { return useableMoney; }
set { useableMoney = value; }
}
}
par :
[DataContract]
public class PlayerInfo
{
private long money;
private long useableMoney;
[DataMember]
public long Money
{
get { return money; }
set { money = value; }
}
[DataMember]
public long UseableMoney
{
get { return useableMoney; }
set { useableMoney = value; }
}
}
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :