Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

NoSoap with WCF (dotNet 3.5) C#

2008-02-24
2013-06-06
  • Voici la solution pour tout ceux qui souahitent utiliser PHP NuSoap Server avec un client Soap en .Net.
    Le code de l'exemple est en C# (tres longue recherche sur google pour trouver 1 solution, donc exemple à difuser).

    Le code PHP du server:

    service.php

    <?php

             function MaProcedure($info)
         {
                 return "L'info est: ".$info;
         }
     
             mb_internal_encoding("UTF-8");

         require_once("lib/nusoap.php");

             $ns = "http://mondomaine";
         $server = new soap_server();
         $server->configureWSDL("SampleService");
         $server->wsdl->schemaTargetNamespace = $ns;
         $server->decode_utf8 = true;
         $server->soap_defencoding = "UTF-8";

         $server->register(
         'MaProcedure',
         array('info' => 'xsd:string'),
         array('return' => 'xsd:string'),
         $ns, false, 'rpc', 'encoded', "SampleService Description");
                   
         $POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
         $server->service($POST_DATA);               
         exit();
        
    ?>

    Et maintenant la partie .Net: (Visual Studio 2008, Visual Studio Express 2008)

    Dans votre projet, ajoutez une référence de service (clique droit sur Reference).

    Dans la fenetre qui s'affiche, dans la boite texte 'Adresse' ajoutez 'http://mondomaine/service.php?wsdl' ou 'mondoamine' correspond a la variable $ns du service PHP, soit le chemin ou se trouve le fichier 'service.php'.

    Cliquez sur 'Aller a'. Apres un tres court moment, le service est découvert. Verifiez bien si vous avez acces à l'integralite du service.

    Dans la case 'Espace de noms' renseignez 'SampleService' soit la valeur passee en parametre de la procedure '$server->configureWSDL("SampleService");' dans le code PHP du service.

    Pour finir, cliquez sur 'OK'. Bon a ce stade, une liaison a votre service est cree dans votre projet.

    Pour l'utiliser cela est simple, dans votre code:

    SampleService.SampleServicePortTypeClient _client = new SampleService.SampleServicePortTypeClient();
    MessageBox.Show( _client.MaProcedure( "meteo" ) );

    Affichera une boite de message contenant:  " L'info est: meteo "

    Bon l'astuce se trouve dans le rensignement de l'encodage dans le code PHP du service:

    WCF cherche à lire du UTF-8, text/xml et le service renvoi du ISO-8859-1, text/xml. Vous me direz ce n'est pas si grave, bah si car cette information sert a WCF comme verification de l'authenticité de la reponse provenant du service et donc par defaut renvoi une exception comme telle:

    " Le type de contenu text/xml; charset=ISO-8859-1 du message de réponse ne correspond pas au type de contenu de la liaison (text/xml; charset=utf-8). Si vous utilisez un codeur personnalisé, vérifiez que la méthode IsContentTypeSupported est implémentée correctement. Les premiers 486 octets de la réponse étaient : « <?xml version="1.0" encoding="ISO-8859-1"?><SOAP-E................. "

    Pour contrer ce problème très simplement voici ce que j'ai ajouté au code PHP par defaut du service:

    mb_internal_encoding("UTF-8"); // harmonise l'encodage

    puis:

    $server->decode_utf8 = true; // permet a la librairie de mieux jongler avec l'ISO-8859-1 et UTF-8

    et pour finir (super important):

    $server->soap_defencoding = "UTF-8"; // permet a soapSerialize d'encoder le flux XML en UTF-8, donc de renvoyer l'encodage attendu par WCF!

    Je ne sais pas si du cote de .NEt il y a une astuce simple pour regler ce probleme (je n'ai trouvé que des usines a gaz) mais cette astuce fonctionne parfaitement.

    Apres pour eviter un probleme d'encodage de vos chaines de caracteres que ce soit du cote .NEt que PHP, je vous conseil de toujours tout encoder en UTF8 (utf8_encode( "Ma chaine" ) / utf8_decode ( "Ma chaine" ) en PHP et Encoding.UTF8.GetString(Encoding.Default.GetBytes( "Ma chaine" )) / Encoding.Default.GetString(Encoding.UTF8.GetBytes( "Ma chaine" )) en C#).

    Voila, si cela peut aider quelqu'un.

    PS: j'ai posté la solution ici, car sourceforge à un tres bon positionnement permanent dans goole, donc ce message pourra apparaitre facilement dans quelque temps dans les recherches google.

     
    • Please modify title!  NuSoap not NoSoap!! excuse me.