<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog de Jérémie Bertrand</title>
	<atom:link href="https://blog.developpez.com/laedit/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/laedit</link>
	<description></description>
	<lastBuildDate>Tue, 22 Mar 2011 14:30:08 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Lancement d&#8217;AppConfig Code Generator</title>
		<link>https://blog.developpez.com/laedit/p9829/c/lancement_d_appconfig_code_generator</link>
		<comments>https://blog.developpez.com/laedit/p9829/c/lancement_d_appconfig_code_generator#comments</comments>
		<pubDate>Tue, 22 Mar 2011 14:30:08 +0000</pubDate>
		<dc:creator><![CDATA[laedit]]></dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Petite news (depuis fort longtemps malheureusement&#8230;) pour annoncer le lancement du projet AppConfig Code Generator ! Hébergé sur codeplex (http://appconfigcodegen.codeplex.com/), ce projet est un Custom Tool pour Visual Studio 2008 et 2010 permettant la génération automatique en C# ou VB.NET d&#8217;une classe d&#8217;accès aux appSettings et connectionStrings contenu dans le fichier App.config du projet. Codé en une journée, ce projet est encore jeune et ne demande qu&#8217;à être amélioré grâce à vos idées, donc n&#8217;hésitez [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Petite news (depuis fort longtemps malheureusement&#8230;) pour annoncer le lancement du projet AppConfig Code Generator !</p>
<p>Hébergé sur codeplex (<a href="http://appconfigcodegen.codeplex.com/">http://appconfigcodegen.codeplex.com/</a>), ce projet est un Custom Tool pour  Visual Studio 2008 et 2010 permettant la génération automatique en C# ou VB.NET d&rsquo;une classe d&rsquo;accès aux appSettings et connectionStrings contenu dans le fichier App.config du projet.</p>
<p>Codé en une journée, ce projet est encore jeune et ne demande qu&rsquo;à être amélioré grâce à vos idées, donc n&rsquo;hésitez pas à aller sur le <a href="http://appconfigcodegen.codeplex.com/">site</a> pour dire ce que vous en pensez !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dessiner un PNG avec le Compact Framework</title>
		<link>https://blog.developpez.com/laedit/p9247/c/dessiner_un_png_avec_le_compact_framewor</link>
		<comments>https://blog.developpez.com/laedit/p9247/c/dessiner_un_png_avec_le_compact_framewor#comments</comments>
		<pubDate>Wed, 01 Sep 2010 13:09:25 +0000</pubDate>
		<dc:creator><![CDATA[laedit]]></dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[PInvoke]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Qui n&#8217;a jamais dû dessiner une image transparente avec le Compact Framework sur Windows Mobile ou pire Windows CE ? Le plus simple est d&#8217;utiliser une image PNG. Le problème étant que le Compact Framework ne prend pas en charge la transparence. Il faut donc utiliser les dlls de l&#8217;OS afin de remédier à ce petit problème. Après un petit tour sur le web,on trouve assez rapidement qu&#8217;il faut utiliser l&#8217;API Imaging. On peut également [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Qui n&rsquo;a jamais dû dessiner une image transparente avec le Compact Framework sur Windows Mobile ou pire Windows CE ?<br />
Le plus simple est d&rsquo;utiliser une image PNG. Le problème étant que le Compact Framework ne prend pas en charge la transparence.</p>
<p>Il faut donc utiliser les dlls de l&rsquo;OS afin de remédier à ce petit problème.</p>
<p><span id="more-11"></span></p>
<p>Après un petit tour sur le web,on trouve assez rapidement qu&rsquo;il faut utiliser l&rsquo;API Imaging. On peut également utiliser l&rsquo;API Alpha blend afin de rendre transparente une image qui ne l&rsquo;est pas, mais les possibilités ne sont pas aussi étendues qu&rsquo;avec une image PNG.</p>
<p>Une fois cette info en poche, un petit tour sur <a href="http://pinvoke.net/">PInvoke.net</a> nous apprend qu&rsquo;il faut utiliser un object COM nous permettant par la suite d&rsquo;avoir une interface IImage, représentant une image transparente, et une interface IImagingFactory, permettant de créer des objets de type IImage.<br />
L&rsquo;imprémentation en est très bien expliqué dans le post <a href="http://blogs.msdn.com/b/chrislorton/archive/2006/04/07/570649.aspx">Alphablending with NETCF</a> de Chris Lorton.</p>
<p>Une fois les diverses structures et interfaces en place, on lance le projet et tout marche, on a de la transparence !</p>
<p>Enfin, pas pour tous. Vous n&rsquo;êtes peut-être pas tombé dessus, mais en changeant les coordonnées du rectangle de destination d&rsquo;une IImage l&rsquo;exception ArgumentException avec le message très explicite &laquo;&nbsp;0x80070057&Prime; peut être levée.<br />
Une fois connue, la raison en est simple : le rectangle de destination ne fonctionne pas exactement de la même manière que dans les autres fonctions de dessin.<br />
Le rectangle est normalement composé de 4 entiers : X et Y représentent les coordonnées du point situé en haut à gauche de la zone à dessiner et Width et Height représentent la largeur et la hauteur de la zone à dessiner.</p>
<p>Mais dans le cas présent, si X et Y gardent la même fonction, c&rsquo;est Width et Height qui sont différents. En effet, ils ne correspondent pas à la largeur et la hauteur du rectangle dont le point en haut à gauche est situé à X,Y  mais à 0,0.</p>
<p>Il faut donc ajouter X à la largeur voulue et Y à la hauteur voulue : </p>
<p><code class="codecolorer text default"><span class="text">Rectangle(X, Y, X + Width, Y + Height)</span></code></p>
<p>Par exemple, j&rsquo;ai une image avec ce rectangle de destination: 0, 0, 50 ,50.</p>
<p>Si je souhaite la déplacer, j&rsquo;aurais donc ce rectangle de destination: 20, 30, 20 + 50, 30 + 50, afin de conserver les proportions de l&rsquo;image.</p>
<p><strong>Update :</strong><br />
Un petit plus afin de gagner du temps lors du dessin, pensez à utiliser la méthode SetImageFlags avec en paramètre ImageFlagsCaching de l&rsquo;objet IImage.<br />
Plus d&rsquo;informations <a href="http://e-consystems.com/blog/creating-an-effective-image-viewer-in-windows-ce/">ici</a> (attention, code non-managé).</p>
<p>Bonne chance avec vos projets Compact Framework !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon Product Advertising API en C#</title>
		<link>https://blog.developpez.com/laedit/p9187/c/amazon_product_advertising_api_en_c</link>
		<comments>https://blog.developpez.com/laedit/p9187/c/amazon_product_advertising_api_en_c#comments</comments>
		<pubDate>Sat, 07 Aug 2010 18:37:34 +0000</pubDate>
		<dc:creator><![CDATA[laedit]]></dc:creator>
				<category><![CDATA[Amazon]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[WebService]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Avez-vous déjà voulu requêter les web services d&#8217;amazon afin de récupérer le titre d&#8217;un film ou d&#8217;un livre ? Si oui, vous vous êtes sûrement déjà confrontés au brouillard de tous les web services amazon afin de trouver le bon, et après il faut encore trouver son nom ( car ils ont tendance à changer ) et à trouver quelques bons exemples de codes encore valable, voire la bonne adresse du WSDL. Après une petite [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Avez-vous déjà voulu requêter les web services d&rsquo;amazon afin de récupérer le titre d&rsquo;un film ou d&rsquo;un livre ?</p>
<p>Si oui, vous vous êtes sûrement déjà confrontés au brouillard de tous les web services amazon afin de trouver le bon, et après il faut encore trouver son nom ( car ils ont tendance à changer ) et à trouver quelques bons exemples de codes encore valable, voire la bonne adresse du WSDL.</p>
<p>Après une petite après-midi de recherche, j&rsquo;ai pu trouver ce que je voulais et arriver au résultat voulu : récupérer toutes les informations d&rsquo;un produit à partir de son code EAN (code-barre).</p>
<p><span id="more-19"></span></p>
<p>Après avoir passé quelques heures sur le site d&rsquo;amazon et m&rsquo;être aperçu que tous les exemples ne sont plus valable, je me suis tourné vers google. Et après quelques recherches infructueuses, j&rsquo;ai trouvé la perle : le code-source et le guide pour réaliser le même code.</p>
<p>Merci Oren Trutner : <a href="https://flyingpies.wordpress.com/2009/08/01/17/">https://flyingpies.wordpress.com/2009/08/01/17/</a></p>
<p>Au passage, il faut se créer un compte pour utiliser les web services d&rsquo;Amazon. Vous pouvez vous en créer un gratuitement à cette adresse : <a href="http://aws.amazon.com/">http://aws.amazon.com/</a> en cliquant sur le lient &laquo;&nbsp;Create an AWS Account&nbsp;&raquo; en haut à droite. Une fois la création effectuée, allez dans Account->Security Credentials et gardez sous la main l&rsquo;Access Key ID et la Secret Access Key dans la partie Access Credentials, vous en aurez besoin par la suite.</p>
<p>Au niveau du code, au début rien de bien compliqué : le WSDL est dispo à l&rsquo;adresse <a href="http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl">http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl</a>.<br />
Il suffit de créer une nouveau projet dans Visual Studio et d&rsquo;ajouter une référence de service avec cette uri, en asynchrone ou non selon vos goûts.<br />
On obtient donc de jolies classes de proxy, que l&rsquo;on peut donc utiliser afin de requêter Amazon.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; class Program <br />
&nbsp; &nbsp; { <br />
&nbsp; &nbsp; &nbsp; &nbsp; // your Amazon ID's <br />
&nbsp; &nbsp; &nbsp; &nbsp; private const string accessKeyId = &quot;AccessKeyId&quot;; <br />
&nbsp; &nbsp; &nbsp; &nbsp; private const string secretKey = &quot;SecretAccessKey&quot;; <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; // the program starts here <br />
&nbsp; &nbsp; &nbsp; &nbsp; static void Main(string[] args) <br />
&nbsp; &nbsp; &nbsp; &nbsp; { <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // create a WCF Amazon ECS client <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AWSECommerceServicePortTypeClient client = new AWSECommerceServicePortTypeClient( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new BasicHttpBinding(), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new EndpointAddress(&quot;http://webservices.amazon.com/onca/soap?Service=AWSECommerceService&quot;)); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // prepare an ItemSearch request <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ItemSearchRequest request = new ItemSearchRequest(); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.SearchIndex = &quot;All&quot;; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.Keywords = &quot;3700259800655&quot;; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.ResponseGroup = new String[] { &quot;Large&quot; }; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ItemSearch itemSearch = new ItemSearch(); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; itemSearch.Request = new ItemSearchRequest[] { request }; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; itemSearch.AWSAccessKeyId = accessKeyId; <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // issue the ItemSearch request <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ItemSearchResponse response = client.ItemSearch(itemSearch); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // write out the results <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach (var item in response.Items[0].Item) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(item.ItemAttributes.Title); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.ReadLine();</div></div>
<p>Pour information, la liste de tous les SearchIndex est ici : <a href="http://docs.amazonwebservices.com/AWSEcommerceService/4-0/ApiReference/SearchIndexValues.html">http://docs.amazonwebservices.com/AWSEcommerceService/4-0/ApiReference/SearchIndexValues.html</a>. Il faut tout de même lui ajouter All, qui correspond à une recherche sur toutes les catégories.</p>
<p>Mais le code précédent ne fonctionne pas. Pas avant d&rsquo;avoir bidouillé un peu. Car ce qu&rsquo;Amazon ne dit pas sur son site (ou alors il fallait chercher pendant encore quelques heures), c&rsquo;est toute la partie authentification des messages SOAP qu&rsquo;il faut mettre en place.<br />
Trois classes vont rendre cela possible :</p>
<ul>
<li>AmazonSigningMessageInspector : implémente IClientMessageInspector et permet de modifier la requête avant son envoi. Elle va donc rajouter les headers.</li>
<li>AmazonSigningEndpointBehavior : implémente IEndpointBehavior et permet d&rsquo;ajouter le bon MessageInspector au bon moment.</li>
<li>AmazonHeader : hérite de MessageHeader et est utilisée par le MessageInspector pour ajouter les headers.</li>
</ul>
<p>Voilà la partie du code de AmazonSigningMessageInspector ajoutant les headers :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp; &nbsp; public object BeforeSendRequest(ref Message request, IClientChannel channel) <br />
&nbsp; &nbsp; &nbsp; &nbsp; { <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // prepare the data to sign <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string operation = Regex.Match(request.Headers.Action, &quot;[^/]+$&quot;).ToString(); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DateTime now = DateTime.UtcNow; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string timestamp = now.ToString(&quot;yyyy-MM-ddTHH:mm:ssZ&quot;); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string signMe = operation + timestamp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; byte[] bytesToSign = Encoding.UTF8.GetBytes(signMe); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // sign the data <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; byte[] secretKeyBytes = Encoding.UTF8.GetBytes(secretKey); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HMAC hmacSha256 = new HMACSHA256(secretKeyBytes); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; byte[] hashBytes = hmacSha256.ComputeHash(bytesToSign); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string signature = Convert.ToBase64String(hashBytes); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // add the signature information to the request headers <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.Headers.Add(new AmazonHeader(&quot;AWSAccessKeyId&quot;, accessKeyId)); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.Headers.Add(new AmazonHeader(&quot;Timestamp&quot;, timestamp)); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.Headers.Add(new AmazonHeader(&quot;Signature&quot;, signature)); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null; <br />
&nbsp; &nbsp; &nbsp; &nbsp; }</div></div>
<p>Cela permettra de mettre en place un header de ce type :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;soap:Header <br />
&nbsp; &nbsp;xmlns:aws=&quot;http://security.amazonaws.com/doc/2007-01-01/&quot;&gt; <br />
&nbsp; &nbsp;&lt;aws:AWSAccessKeyId&gt;YOURACCESSKEYIDHEREX&lt;/aws:AWSAccessKeyId&gt; <br />
&nbsp; &nbsp;&lt;aws:Timestamp&gt;2009-08-15T23:59:59Z&lt;/aws:Timestamp&gt; <br />
&nbsp; &nbsp;&lt;aws:Signature&gt;SZf1CHmQnrZbsrC13hCZS061ywsEXAMPLE&lt;/aws:Signature&gt; <br />
&lt;/soap:Header&gt;</div></div>
<p>Il suffit ensuite de modifier la façon d&rsquo;appeler le web service pour que tout roule :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // create a WCF Amazon ECS client <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; binding.MaxReceivedMessageSize = int.MaxValue; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AWSECommerceServicePortTypeClient client = new AWSECommerceServicePortTypeClient( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; binding, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new EndpointAddress(&quot;http://webservices.amazon.com/onca/soap?Service=AWSECommerceService&quot;)); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // add authentication to the ECS client <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.ChannelFactory.Endpoint.Behaviors.Add(new AmazonSigningEndpointBehavior(accessKeyId, secretKey));</div></div>
<p>Et afin de pouvoir &laquo;&nbsp;localiser&nbsp;&raquo; les web services, j&rsquo;ai créée une petite classe AmazonEndpointAdress recensant toutes les adresses des endpoint des web services Amazon, accessibles ici : <a href="http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?AnatomyOfaRESTRequest.html">http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?AnatomyOfaRESTRequest.html</a>.<br />
Bien entendu, votre fichier App.config doit comporter tous les endpoint correspondant.<br />
Et au final, le code d&rsquo;appel ressemble à celle-ci :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">AWSECommerceServicePortTypeClient client = new AWSECommerceServicePortTypeClient( <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; binding, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new EndpointAddress(AmazonEndpointAdresses.FR));</div></div>
<p>Et voilà !</p>
<p>Vous pouvez maintenant rechercher n&rsquo;importe quel produit sur n&rsquo;importe quel site d&rsquo;Amazon !</p>
<p>Les sources sont disponibles ici : <a href="http://laedit.ftp-developpez.com/CSharp/Amazon/AmazonProductAdvtApiWcfSample.zip">http://laedit.ftp-developpez.com/CSharp/Amazon/AmazonProductAdvtApiWcfSample.zip</a>.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Convertir des fichiers XPS en PDF</title>
		<link>https://blog.developpez.com/laedit/p8983/news/convertir_des_fichiers_xps_en_pdf</link>
		<comments>https://blog.developpez.com/laedit/p8983/news/convertir_des_fichiers_xps_en_pdf#comments</comments>
		<pubDate>Tue, 08 Jun 2010 15:20:24 +0000</pubDate>
		<dc:creator><![CDATA[laedit]]></dc:creator>
				<category><![CDATA[Divers]]></category>
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pour une fois, ce post ne parlera pas de développement. Enfin si, mais indirectement. Vous êtes-vous déjà retrouvé à devoir convertir des fichiers XPS en PDF ? Vous avez probablement utilisé une imprimante PDF telle que PDFCreator ou CuteWriter. Et cela à fonctionné. Mais si vous utilisez Reflector et son addin SequenceViz afin d&#8217;exporter rapidement vos diagrammes de séquences, les fichiers XPS générés donnent une page blanche (ou presque) une fois imprimé en PDF. Après [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Pour une fois, ce post ne parlera pas de développement. Enfin si, mais indirectement.</p>
<p>Vous êtes-vous déjà retrouvé à devoir convertir des fichiers XPS en PDF ?<br />
Vous avez probablement utilisé une imprimante PDF telle que PDFCreator ou CuteWriter. Et cela à fonctionné.</p>
<p>Mais si vous utilisez Reflector et son addin SequenceViz afin d&rsquo;exporter rapidement vos diagrammes de séquences, les fichiers XPS générés donnent une page blanche (ou presque) une fois imprimé en PDF.</p>
<p><span id="more-20"></span></p>
<p>Après quelques heures de recherches sur le net et de tests de diverses méthodes (sites web de conversion, programmes divers, imprimantes PDF) donnant des résultats pas toujours probant, j&rsquo;ai fini par mettre la main sur un site qui allie la qualité à la rapidité.</p>
<p>Il suffit d&rsquo;indiquer le fichier à convertir ainsi que son adresse mail afin de pouvoir récupérer le document converti, et en moins de deux minutes le résultat est là.</p>
<p>Voilà l&rsquo;adresse du site : <a href="http://pdf.tchwork.com/fr/">http://pdf.tchwork.com/fr/</a></p>
<p>Petit plus, le site gère aussi la conversion des formats suivants en PDF : .doc, .docx, .rtf, .xls, .ppt, .ps, .eps, .pdf, .dwg, .dwf, .dst, .xps, .odt, .sxw, .sdw, .jtd, .hwp, .wps, .ods, .sxc, .sdc, .dif, .dbf, .slk, .csv, .wk1, .123, .pxl, .wb2, .odp, .sxi, .sda, .sdd, .sdp, .cgm, .odg, .sxd, .dxf</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Guide de programmation MEF</title>
		<link>https://blog.developpez.com/laedit/p8951/c/guide_de_programmation_mef</link>
		<comments>https://blog.developpez.com/laedit/p8951/c/guide_de_programmation_mef#comments</comments>
		<pubDate>Mon, 31 May 2010 08:00:00 +0000</pubDate>
		<dc:creator><![CDATA[laedit]]></dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[MEF]]></category>
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Après plus d&#8217;un mois de traduction, relecture et corrections diverses, je viens enfin de terminer un joli petit dossier sur l&#8217;utilisation de MEF (Managed Extensibility Framework), le framework permettant de créer facilement une application pouvant être étendue par le biais de plugins. Sans plus attendre, voici le lien vers l&#8217;article : http://laedit.developpez.com/CSharp/MEF/Programming_Guide/ Et le sommaire : I. Introduction I-A. Qu&#8217;est-ce que MEF I-B. Quels sont les problèmes que MEF peut résoudre I-C. Comment fonctionne MEF [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Après plus d&rsquo;un mois de traduction, relecture et corrections diverses, je viens enfin de terminer un joli petit dossier sur l&rsquo;utilisation de MEF (Managed Extensibility Framework), le framework permettant de créer facilement une application pouvant être étendue par le biais de plugins.<br />
<span id="more-1"></span></p>
<p>Sans plus attendre, voici le lien vers l&rsquo;article : http://laedit.developpez.com/CSharp/MEF/Programming_Guide/</p>
<p>Et le sommaire :</p>
<blockquote><p>I. Introduction<br />
    I-A. Qu&rsquo;est-ce que MEF<br />
    I-B. Quels sont les problèmes que MEF peut résoudre<br />
    I-C. Comment fonctionne MEF<br />
    I-D. Vue d&rsquo;ensemble de l&rsquo;architecture</p>
<p>II. Guide de programmation MEF<br />
    II-A. Héberger MEF dans une application<br />
        II-A-1. Ajout d&rsquo;une Part directement dans le container<br />
        II-A-2. Ajout en utilisant un AssemblyCatalog<br />
    II-B. Définition des Composable Parts et des contrats<br />
        II-B-1. Composable Part<br />
        II-B-2. Contrats<br />
            II-B-2-1. Contrats d&rsquo;interface / abstraits<br />
        II-B-3. Assemblage de contrats<br />
    II-C. Déclaration des exports<br />
        II-C-1. Export de Composable Part<br />
        II-C-2. Export de propriétés<br />
        II-C-3. Export de méthodes<br />
        II-C-4. Héritage d&rsquo;export<br />
        II-C-5. Découverte de Composable Parts privées<br />
    II-D. Déclaration des imports<br />
        II-D-1. Import de propriétés<br />
        II-D-2. Paramètre de constructeur<br />
            II-D-2-1. Import de paramètres<br />
        II-D-3. Import de champs<br />
        II-D-4. Imports optionnels<br />
        II-D-5. Import de collections<br />
        II-D-6. IPartImportsSatisfiedNotification<br />
    II-E. Imports différés<br />
    II-F. Exports et métadonnées<br />
        II-F-1. Ajouter des métadonnées à un export<br />
            II-F-1-1. Utiliser l&rsquo;attribut ExportMetadata<br />
            II-F-1-2. Utiliser un attribut d&rsquo;export personnalisé<br />
        II-F-2. Importer des métadonnées<br />
            II-F-2-1. Utiliser des métadonnées fortement typées<br />
            II-F-2-2. Utiliser des métadonnées faiblement typées<br />
            II-F-2-3. Le filtrage des métadonnées et l&rsquo;attribut DefaultValueAttribute<br />
    II-G. Utilisation des catalogues<br />
        II-G-1. AssemblyCatalog<br />
        II-G-2. DirectoryCatalog<br />
        II-G-3. AggregateCatalog<br />
        II-G-4. TypeCatalog<br />
        II-G-5. DeploymentCatalog &#8211; uniquement dans Silverlight<br />
        II-G-6. Utilisation d&rsquo;un catalogue dans un Container<br />
    II-H. Catalogues filtrés<br />
    II-I. Cycle de vie des Parts<br />
        II-I-1. Shared, Non Shared et propriété<br />
        II-I-2. Disposer le container<br />
        II-I-3. Container et références des Parts<br />
        II-I-4. Scoped operations et récupération rapide des ressources<br />
        II-I-5. Hiérarchie des containers<br />
        II-I-6. Ordre de disposition<br />
        II-I-7. AddPart / RemovePart<br />
    II-J. Recomposition<br />
        II-J-1. Mises en garde<br />
        II-J-2. La recomposition et Silverlight<br />
    II-K. Requêter le CompositionContainer<br />
        II-K-1. GetExportedValue<br />
        II-K-2. GetExport<br />
        II-K-3. GetExportedValueOrDefault<br />
    II-L. Composition Batch<br />
    II-M. Débogage et diagnostics<br />
        II-M-1. Diagnostiquer les problèmes de composition<br />
            II-M-1-1. Problèmes liés au rejet<br />
            II-M-1-2. Dump Composition State<br />
            II-M-1-3. Trouver les root causes probables<br />
            II-M-1-4. Débogage des proxies<br />
        II-M-2. Mefx : outil d&rsquo;analyse en ligne de commande<br />
        II-M-3. Tracer les informations de composition<br />
    II-N. FAQ<br />
        II-N-1. Comment avoir des exports utilisant un objet Type<br />
        II-N-2. Comment utiliser des containers imbriqués</p>
<p>III. Fonctionnalités spécifiques à Silverlight<br />
    III-A. Héberger MEF dans Silverlight en utilisant le CompositionInitializer<br />
        III-A-1. Utilisation de CompositionInitializer depuis des éléments XAML<br />
        III-A-2. Mises en garde dans l&rsquo;utilisation de CompositionInitializer.SatisfyImports<br />
    III-B. Redéfinir la configuration de l&rsquo;hôte<br />
        III-B-1. Redéfinition grâce aux catalogues<br />
            III-B-1-1. Configurer la découverte des Parts dans le XAP courant<br />
        III-B-2. Redéfinition grâce à un container<br />
    III-C. Instanciation dynamique et ExportFactory&lt;T&gt;<br />
        III-C-1. ExportFactory&lt;T&gt;<br />
        III-C-2. ExportLifetimeContext&lt;T&gt;<br />
    III-D. Partitionnement d&rsquo;application avec le DeploymentCatalog<br />
        III-D-1. DeploymentCatalog<br />
        III-D-2. Télécharger des Parts après le démarrage de l&rsquo;application<br />
        III-D-3. Composer dynamiquement les Parts téléchargées et utiliser la recomposition<br />
        III-D-4. Téléchargement des Parts à la demande après démarrage de l&rsquo;application et basé sur les actions de l&rsquo;utilisateur<br />
        III-D-5. Gestion des erreurs durant le téléchargement<br />
        III-D-6. Mise à jour de la progression<br />
        III-D-7. Annulation du téléchargement<br />
        III-D-8. Utilisation du DeploymentCatalog quand l&rsquo;application est hors-ligne ou Out of Browser<br />
        III-D-9. Mises en garde contre l&rsquo;utilisation du DeploymentCatalog</p>
<p>IV. Codes sources et exemples<br />
V. Liens<br />
VI. Remerciements<br />
VII. Contact</p></blockquote>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Utiliser Business Objects dans une application C#</title>
		<link>https://blog.developpez.com/laedit/p8822/c/utiliser_business_objects_dans_une_appli</link>
		<comments>https://blog.developpez.com/laedit/p8822/c/utiliser_business_objects_dans_une_appli#comments</comments>
		<pubDate>Thu, 15 Apr 2010 07:48:01 +0000</pubDate>
		<dc:creator><![CDATA[laedit]]></dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Business Objects]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[XI R2]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Vu que je me retrouve embarquer là dedans pour des raisons professionnelles, et que j&#8217;ai galéré à trouver des infos, voilà comment faire pour utiliser Business Objects XI R2 dans une application C#. Première étape, et non des moindres, installer BO. Je ne vais pas détailler le processus ici, je préfère me concentrer sur du technique. Et puis c&#8217;est pas bien compliqué :p Une fois l&#8217;installation finie, des dlls ont été installés dans le dossier [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Vu que je me retrouve embarquer là dedans pour des raisons professionnelles, et que j&rsquo;ai galéré à trouver des infos, voilà comment faire pour utiliser Business Objects XI R2 dans une application C#.</p>
<p><span id="more-16"></span></p>
<p>
Première étape, et non des moindres, installer BO.</p>
<p>Je ne vais pas détailler le processus ici, je préfère me concentrer sur du technique. Et puis c&rsquo;est pas bien compliqué :p</p>
<p>Une fois l&rsquo;installation finie, des dlls ont été installés dans le dossier System32, d&rsquo;autres se retrouvent dans le GAC (C:\WINDOWS\assembly), tandis que d&rsquo;autres encore sont présentes dans un des dossiers du dossier d&rsquo;installation de BO, qui est par défaut &laquo;&nbsp;C:\Program Files\Business Objects\BusinessObjects Enterprise 11.5\win32_x86\&nbsp;&raquo;.<br />
[Update] D&rsquo;autres dlls (pour les types de fichiers par exemple), sont présentes dans le dossier &laquo;&nbsp;C:\Program Files\Business Objects\common\3.5\managed&nbsp;&raquo;.</p>
<p>Parmi les dlls présentes dans le GAC, trois vont nous intéresser :</p>
<ul>
<li>CrystalDecisions.Enterprise.dll</li>
<li>CrystalDecisions.Enterprise.Framework.dll</li>
<li>CrystalDecisions.Enterprise.InfoStore.dll</li>
</ul>
<p>
Ce sont celles qui vont nous permettre de faire des requêtes dans l&rsquo;InfoStore de BO et ainsi récupérer, modifier ou supprimer divers objets BO.
</p>
<p>
Pour tester tout ça, il suffit maintenant de créer une application C#. Une application console fera l&rsquo;affaire.</p>
<p>Ne pas oublier de référencer les trois dlls citées précédemment.</p>
<p>Et maintenant place au code :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; // Création d'un sessionManager, c'est lui qui va nous permettre de nous identifier <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SessionMgr boSessionMgr = new SessionMgr(); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Connexion à un serveur BO et récupération de la session &nbsp; &nbsp;[login] &nbsp; &nbsp; &nbsp;[mot de passe] &nbsp; [CMS name] &nbsp; &nbsp; [type d'authentification] <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;EnterpriseSession boEnterpriseSession = boSessionMgr.Logon(&quot;administrator&quot;, string.Empty, &quot;VMSqlServer05&quot;, &quot;Enterprise&quot;); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Récupération d'un InfoStore afin de faire des requêtes <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;InfoStore boInfoStore = new InfoStore(boEnterpriseSession.GetService(SERVICE_INFOSTORE)); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Récupération d'une liste d'objets BO grâce à une requête dans l'InfoStore <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;InfoObjects boObjects = boInfoStore.Query(&quot;Select * From CI_INFOOBJECTS WHERE SI_KIND != 'Inbox' AND SI_KIND != 'PersonalCategory' ORDER BY SI_ID&quot;); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Affichage des CUID et ID des objets <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;foreach (InfoObject infoObject in boObjects) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(infoObject.CUID + &quot; : &quot; + infoObject.ID); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Modification d'un objet&quot;); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Modification du titre du premier objet récupéré <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Attention, dans BO les listes d'objets (InfoObjects) commencent à 1 et non à 0 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;boObjects[1].Title = newTitle; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Enregistrement des modifications dans l'InfoStore de BO <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;boInfoStore.Commit(boObjects); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Objet modifié&quot;); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch (COMException COMEx) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;ErrorCode: &quot; + COMEx.ErrorCode); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Message: &quot; + COMEx.Message); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;StackTrace: &quot; + COMEx.StackTrace); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.ReadLine();</div></div>
<p>Ce code détaillé permet donc de se connecter à BO, de récupérer une liste d&rsquo;objet et de modifier l&rsquo;un d&rsquo;entre eux. Histoire de connaître les bases des relations entre BO et C# <img src="https://blog.developpez.com/laedit/wp-includes/images/smilies/icon_biggrin.gif" alt=":D" class="wp-smiley" />
</p>
<p>
Si une erreur survient lors de l&rsquo;instanciation du SessionMgr, c&rsquo;est que la dll EnterpriseFramework.dll, qui est présente dans le dossier &laquo;&nbsp;win32_x86&Prime; du dossier d&rsquo;installation de BO, n&rsquo;a pas été installée. Il faut donc le faire via la ligne de commande &laquo;&nbsp;regsvr32 EnterpriseFramework.dll&nbsp;&raquo;.
</p>
<p>Et pour finir, voici quelques bons liens :</p>
<ul>
<li><a href="http://books.google.fr/books?id=UO9MHMt91dcC&amp;pg=PA193&amp;lpg=PA193&amp;dq=BusinessObjects+XI+.NET+Providers&amp;source=bl&amp;ots=rtdnB0Zy88&amp;sig=88OFW9cX5qa5Rm_6JaXHQ5bQ9LM&amp;hl=fr&amp;ei=YW_ES_3sIoePsAb9mrGkDg&amp;sa=X&amp;oi=book_result&amp;ct=result&amp;resnum=7&amp;ved=0CDkQ6AEwBg#v=onepage&amp;q=BusinessObjects%20XI%20.NET%20Providers&amp;f=false">Pro Crystal Enterprise/Business Objects XI programming</a> Par Carl Ganz : aperçu d&rsquo;un très bon livre sur la programmation avec BO</li>
<li><a href="http://www.businessobjectstips.com/tips/server/querying-the-busines-objects-xi-cms-infostore-database-tables/">Querying the Busines Objects XI CMS InfoStore Database Tables</a> : un très bon tips sur les requêtages des tables de l&rsquo;InfoStore</li>
<li><a href="http://devlibrary.businessobjects.com/BusinessObjectsXIR2/en/devsuite.htm#en/WS_SDK/default.htm">La doc officielle de Business Objects XI R2</a></li>
<li><a href="http://www.sdn.sap.com/irj/boc/sdklibrary">La doc officielle chez SAP</a> avec deux sections intéressantes :</li>
<li><a href="http://www.sdn.sap.com/irj/boc/sdklibrary#section7">.NET SDK Developer Guides and API References</a></li>
<li><a href="http://www.sdn.sap.com/irj/boc/sdklibrary#section17">Object Model Diagrams</a></li>
</ul>
<p>
J&rsquo;espère qu&rsquo;avec ceci vous ne perdrez pas autant de temps que moi à trouver des informations sur comment utiliser BO via une application C# !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Twoolr : toutes les statistiques sur votre compte twitter</title>
		<link>https://blog.developpez.com/laedit/p8881/news/twoolr_toutes_les_statistiques_sur_votre</link>
		<comments>https://blog.developpez.com/laedit/p8881/news/twoolr_toutes_les_statistiques_sur_votre#comments</comments>
		<pubDate>Wed, 28 Apr 2010 06:58:03 +0000</pubDate>
		<dc:creator><![CDATA[laedit]]></dc:creator>
				<category><![CDATA[Divers]]></category>
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Des statistiques d&#8217;utilisation aussi bien que des statistiques de réseau, en passant par quel heure/jour/semaine/mois vous êtes le plus actif, quels clients vous utilisez, les liens que vous avez envoyés, qui vous réponds le plus, etc&#8230; Même si toutes ne sont pas forcément utiles (en tout cas pour des particuliers), ça s&#8217;avère tout de même intéressant à essayer. Twoolr est actuellement en phase beta et nécessite un token, par chance 10 sont disponibles en passant [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Des statistiques d&rsquo;utilisation aussi bien que des statistiques de réseau, en passant par quel heure/jour/semaine/mois vous êtes le plus actif, quels clients vous utilisez, les liens que vous avez envoyés, qui vous réponds le plus, etc&#8230;</p>
<p>Même si toutes ne sont pas forcément utiles (en tout cas pour des particuliers), ça s&rsquo;avère tout de même intéressant à essayer.</p>
<p>Twoolr est actuellement en phase beta et nécessite un token, par chance 10 sont disponibles en passant par l&rsquo;url suivante : http://laedit.twoolr.com</p>
<p>Bonne twittistiques ! <img src="https://blog.developpez.com/laedit/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Créer un addin pour Firefox</title>
		<link>https://blog.developpez.com/laedit/p8873/articles/creer_un_addin_pour_firefox</link>
		<comments>https://blog.developpez.com/laedit/p8873/articles/creer_un_addin_pour_firefox#comments</comments>
		<pubDate>Mon, 26 Apr 2010 21:03:06 +0000</pubDate>
		<dc:creator><![CDATA[laedit]]></dc:creator>
				<category><![CDATA[Addin]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Firefox]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Même si à première vue la création d&#8217;un addin pour Firefox peut paraître simple, certaines choses sont à connaître si on ne veut pas galérer plus que nécessaire. Voilà donc une liste de truc et astuces / tutoriels qui vous aidera à développer plus facilement des plugins pour Firefox. Tout d&#8217;abord, voici un tutoriel sur BornGeek détaillant au pas à pas la création d&#8217;un addin pour Firefox. Très bien fait, il suffit à lui seul [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Même si à première vue la création d&rsquo;un addin pour Firefox peut paraître simple, certaines choses sont à connaître si on ne veut pas galérer plus que nécessaire. Voilà donc une liste de truc et astuces / tutoriels qui vous aidera à développer plus facilement des plugins pour Firefox.</p>
<p><span id="more-18"></span></p>
<p>Tout d&rsquo;abord, voici un tutoriel sur <a href="http://www.borngeek.com/firefox/toolbar-tutorial/">BornGeek</a> détaillant au pas à pas la création d&rsquo;un addin pour Firefox. Très bien fait, il suffit à lui seul pour la création d&rsquo;addins basiques.</p>
<p>En parallèle, le <a href="https://addons.mozilla.org/fr/developers">pôle développeur du site des addins de Firefox</a> comprend des tutoriels ainsi que des articles assez intéressants, de même que <a href="https://developer.mozilla.org/En">l&rsquo;espace développeur de Mozilla</a> contient toute la documentation requise.</p>
<p>Mais certaines choses, même si elles ne sont pas obligatoires, valent mieux pour notre addin quand elles sont respectées. Je pense par exemple à la partie javascript de l&rsquo;addin, certaines règles sont à respecter pour une meilleure intégration avec Firefox. Mark A. Ziesemer a rédigé un <a href="http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html">article</a> sur la question, tandis qu&rsquo;un <a href="https://developer.mozilla.org/en/javascript_style_guide">guide de programmation</a> est présent sur l&rsquo;espace développeur de mozilla.</p>
<p>Une chose à connaître aussi est le cache de Firefox. Mettons par exemple que notre addin va contacter un fichier XML distant afin de récupérer des informations. Le cache de Firefox va fausser cette récupération, faisant croire à l&rsquo;addin que le fichier n&rsquo;a pas été modifié alors qu&rsquo;en réalité c&rsquo;est le cas. Il suffit alors d&rsquo;utiliser la fonction Math.random() en javascript, et d&rsquo;ajouter le résultat en tant que paramètre de l&rsquo;url, afin de faire croire à Firefox que l&rsquo;url n&rsquo;est jamais la même. Ainsi nous n&rsquo;aurons pas le contenu du cache mais le vrai fichier XML.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&quot;http://www.example.com/toolbar/infos.xml?&quot;+Math.random()</div></div>
<p>Une autre chose à savoir est que l&rsquo;utilisation de la méthode Load de XMLDOM sur une fichier distant peut provoquer une erreur de sécurité, ce qui n&rsquo;est pas le cas avec un XMLHttpRequest. Ce dernier est donc à privilégier.</p>
<p>La méthode setTimeout est dépréciée par Mozilla, il faudra donc utiliser à la place une classe interne. Il s&rsquo;agit de la classe <a href="https://developer.mozilla.org/en/nsITimer">timer</a>, qui s&rsquo;instancie de la façon suivante :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">var timer = Components.classes[&quot;@mozilla.org/timer;1&quot;].createInstance(Components.interfaces.nsITimer);</div></div>
<p>Et pour lancer un compte à rebours, on peut utiliser sa méthode initWithCallback :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">timer.initWithCallback(loadEvent, 2000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);</div></div>
<p>loadEvent est un objet implémentant la méthode notify, qui sera utilisée par le timer :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">var loadEvent = { <br />
&nbsp; &nbsp; notify: function(timer) <br />
&nbsp; &nbsp; { <br />
&nbsp; &nbsp; &nbsp; alert('fin du timer'); <br />
&nbsp; &nbsp; } <br />
&nbsp; };</div></div>
<p>Dans cet exemple, au bout de 2 secondes une fenêtre s&rsquo;affichera, marquant &laquo;&nbsp;fin du timer&nbsp;&raquo;.</p>
<p>Un service pratique est celui des observers, permettant entre autre de savoir quand votre addin a été désinstallé.<br />
Il faut tout d&rsquo;abord instancier ce service :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">var observerService = Components.classes['@mozilla.org/observer-service;1'].getService(Components.interfaces.nsIObserverService);</div></div>
<p>Il faut ensuite rajouter un observer, en définissant un objet définissant une méthode observe, ainsi que le type de l&rsquo;observer :</p>
<p><code class="codecolorer text default"><span class="text">observerService.addObserver(uninstallObserver, &quot;em-action-requested&quot;, false);</span></code></p>
<p>uninstallObserver est l&rsquo;objet implémentant la méthode observe, regardons son code :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">var uninstallObserver = { <br />
&nbsp; &nbsp; &nbsp; observe: function(aSubject, aTopic, aData) { <br />
&nbsp; &nbsp; &nbsp; &nbsp; try { <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var item = aSubject.QueryInterface(Components.interfaces.nsIUpdateItem); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (item.id != PLUGIN_ID) { <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (aData == &quot;item-uninstalled&quot;) { <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preferencesService.deleteBranch(&quot;extensions.toolbar&quot;); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } <br />
&nbsp; &nbsp; &nbsp; &nbsp; } catch (e) { <br />
&nbsp; &nbsp; &nbsp; &nbsp; } <br />
&nbsp; &nbsp; &nbsp; } <br />
&nbsp; &nbsp; };</div></div>
<p>L&rsquo;id du plugin ayant levé cet appel est récupéré puis comparé à l&rsquo;id de notre plugin (PLUGIN_ID est une constante ayant pour valeur l&rsquo;id du plugin définit dans le fichier install.rdf). Si c&rsquo;est bien notre plugin qui est à la source de cet appel, et si l&rsquo;action est la désinstallation de ce plugin, alors les préférences du plugin appartenant à la branche &laquo;&nbsp;extensions.toolbar&nbsp;&raquo; sont supprimmées.</p>
<p>Pour rester sur les préférences, qui sont déjà vues dans le <a href="http://www.borngeek.com/firefox/toolbar-tutorial/chapter-6/">tutoriel de BornGeek</a>, un autre <a href="http://www.rietta.com/firefox/Tutorial/prefs.html">tutoriel sur rietta.com</a> les décrit plus en détail, ainsi que la <a href="https://developer.mozilla.org/en/nsIPrefBranch">documentation officielle sur mozilla.org.</a><br />
Avec tout ça, plus aucune excuse pour ne pas les utiliser dans votre addin ! <img src="https://blog.developpez.com/laedit/wp-includes/images/smilies/icon_biggrin.gif" alt=":D" class="wp-smiley" /></p>
<p>Une autre chose à connaître est l&rsquo;eventListener, qui permet par exemple de lancer une action lors du chargement de Firefox. Combiné aux préférences, ça permet par exemple d&rsquo;ouvrir un onglet avec une page vers votre site lors du premier lancement de Firefox après avoir installé votre addin.<br />
Il faut tout d&rsquo;abord ajouter un eventListener :<br />
<code class="codecolorer text default"><span class="text">window.addEventListener(&quot;load&quot;, eventLoad, false);</span></code><br />
Avec le code précédant, on se branche sur l&rsquo;événement load de Firefox. eventLoad est une méthode qui sera appelée à ce moment là.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">function eventLoad () <br />
&nbsp; { <br />
&nbsp; &nbsp; if(preferencesService.getBoolPref(PREF_FIRSTRUN)) <br />
&nbsp; &nbsp; { <br />
&nbsp; &nbsp; &nbsp; preferencesService.setBoolPref(PREF_FIRSTRUN, false); <br />
&nbsp; &nbsp; &nbsp; timer.initWithCallback(loadEvent, 2000, Components.interfaces.nsITimer.TYPE_ONE_SHOT); <br />
&nbsp; &nbsp; } <br />
&nbsp; }</div></div>
<p>PREF_FIRSTRUN est une constante contenant le nom de la préférence qui va indiquer si c&rsquo;est le premier lancement de Firefox depuis l&rsquo;installation de l&rsquo;addin. Si c&rsquo;est le cas, la préférence est modifiée, et un compte à rebours est déclenché via le timer. Il suffira alors de mettre le code suivant dans loadEvent afin d&rsquo;ouvrir un nouvel onglet :</p>
<p><code class="codecolorer text default"><span class="text">gBrowser.selectedTab = gBrowser.addTab(&quot;http://www.google.com&quot;);</span></code></p>
<p>Passons maintenant au déploiement et aux mises à jours.<br />
Le premier est déjà abordé dans le <a href="http://www.borngeek.com/firefox/toolbar-tutorial/chapter-7/">tutoriel de BornGeek</a> ainsi que sur <a href="https://developer.mozilla.org/en/Install.rdf">mozilla.org</a> et n&rsquo;est pas bien compliqué. A partir de là vous pouvez tester votre addin.<br />
Quand aux mises à jour, il suffit de connaître le process pour que ça passe tout seul. Il est décrit dans un autre <a href="http://www.borngeek.com/firefox/automatic-firefox-extension-updates/">article de BornGeek</a> ainsi que sur <a href="https://developer.mozilla.org/en/Extension_Versioning,_Update_and_Compatibility">mozilla.org</a>.<br />
L&rsquo;ordre à retenir est le suivant :<br />
&#8211; Ajout de la clé dans le fichier install.rdf via McCoy<br />
&#8211; Création du XPI<br />
&#8211; Récupération du hash du XPI<br />
&#8211; Ajout du hash dans le fichier update.rdf dans la section correspondante<br />
&#8211; Signature du fichier update.rdf via McCoy</p>
<p>Il ne faut pas retoucher le fichier update.rdf sous peine de devoir le resigner.</p>
<p>Pour le hash, il existe une exention shell pour windows, <a href="http://beeblebrox.org/">HashTab</a>,  qui permet d&rsquo;avoir le hash d&rsquo;un fichier à partir d&rsquo;un simple clic-droit -> propriété.</p>
<p>Update:</p>
<p>Depuis j&rsquo;ai eu à faire une chose dont je suis pas fier : ouvrir le menu lors du passage de la souris.<br />
C&rsquo;est pas ergonomique du tout et ça bouleverse les habitudes des utilisateurs, mais quand on décide pas&#8230;<br />
Du coup, pour mettre ça en place je me suis d&rsquo;abord dit que ça allait être simple, il y a sûrement un event onmouseover auquel préciser une méthode javascript et ça roulerait.<br />
Bah en fait non. Bon, bah alors y&rsquo;a plus qu&rsquo;à rajouter un eventlistener sur le mouseover de l&rsquo;élément que j&rsquo;me suis dit. Oui, mais lors du chargement de la feuile .js, l&rsquo;élément n&rsquo;est pas encore défini. Solution : ajouter un eventlistener sur le load de la fenêtre, et dans le load, ajouter un eventlistener sur le mouseover de l&rsquo;élément ciblé. Et dans le mouseover, on peut enfin ouvrir le menu.<br />
Plus de code pour plus de comprégension :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; window.addEventListener(&quot;load&quot;, PlopTB_Load, false); <br />
&nbsp;<br />
&nbsp;<br />
&nbsp; &nbsp; function PlopTB_Load () <br />
&nbsp; &nbsp; { <br />
&nbsp; document.getElementById('PlopTB-MainMenu').addEventListener(&quot;mouseover&quot;, PlopTB_MainMenuMouseOver, false); &nbsp; <br />
&nbsp; &nbsp; }, <br />
&nbsp;<br />
&nbsp; &nbsp; function PlopTB_MainMenuMouseOver () <br />
&nbsp; &nbsp; { <br />
&nbsp; var toolbarButton = document.getElementById('PlopTB-MainMenu'); <br />
&nbsp; if(!toolbarButton.open) <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; toolbarButton.open = true; <br />
&nbsp; } <br />
&nbsp; &nbsp; }</div></div>
<p>Et voilà qui termine cette série de liens et trucs et astuces, en vous souhaitant un bon développement d&rsquo;addin Firefox !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code Header Designer</title>
		<link>https://blog.developpez.com/laedit/p8037/c/code_header_designer</link>
		<comments>https://blog.developpez.com/laedit/p8037/c/code_header_designer#comments</comments>
		<pubDate>Mon, 07 Sep 2009 18:15:13 +0000</pubDate>
		<dc:creator><![CDATA[laedit]]></dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Divers]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[J&#8217;ai découvert ce week end une application assez sympathique. Elle n&#8217;a qu&#8217;un seul but mais le fait bien, elle permet de définir un header et un footer à rajouter/remplacer à des fichiers de codes. Certes, ce n&#8217;est pas une chose que l&#8217;on fait souvent, mais quand on prend l&#8217;habitude de partager son code, c&#8217;est toujours bien de laisser une trace. Et même pour soi, garder certaines informations en entête peut être utile. Présentation En premier [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>J&rsquo;ai découvert ce week end une application assez sympathique. Elle n&rsquo;a qu&rsquo;un seul but mais le fait bien, elle permet de définir un header et un footer à rajouter/remplacer à des fichiers de codes.</p>
<p>Certes, ce n&rsquo;est pas une chose que l&rsquo;on fait souvent, mais quand on prend l&rsquo;habitude de partager son code, c&rsquo;est toujours bien de laisser une trace. Et même pour soi, garder certaines informations en entête peut être utile.</p>
<p><span id="more-14"></span></p>
<p><strong>Présentation</strong></p>
<p>En premier lieu, l&rsquo;utilisateur va définir un header via un template, comme celui-ci par exemple :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">/* &nbsp;---------------------------------------------------------------------------- <br />
&nbsp;* &nbsp;[COMPANY NAME] <br />
&nbsp;* &nbsp;---------------------------------------------------------------------------- <br />
&nbsp;* &nbsp;[PRODUCT NAME] <br />
&nbsp;* &nbsp;---------------------------------------------------------------------------- <br />
&nbsp;* &nbsp;File: &nbsp; &nbsp; &nbsp; [AUTO:FILE] <br />
&nbsp;* &nbsp;Author: &nbsp; &nbsp; [AUTO:AUTHOR] <br />
&nbsp;* &nbsp;---------------------------------------------------------------------------- <br />
&nbsp;*/</div></div>
<p>Entre crochet, ce sont des champs remplaçables. On définira donc par la suite leur valeur.<br />
Les champs commençant par &lsquo;AUTO:&rsquo; sont des champs automatiques : ils seront automatiquement remplacés par le programme, sans que l&rsquo;utilisateur ai besoin de définir une valeur de remplacement.</p>
<p>De base, on dispose de deux champs auto :<br />
 &#8211; File qui va être remplacé par le nom du fichier<br />
 &#8211; Author qui va être remplacé par le nom d&rsquo;utilisateur windows</p>
<p>Ensuite, on va donc définir les champs à remplacer via un DataGridView :<br />
<img src="http://blog.developpez.com/media/DataGridViewReplaceFields.jpg" width="677" height="213" alt="DataGridView ReplaceFields" /></p>
<p>Il faut maintenant sélectionner les fichiers auxquels on veut appliquer le header. Pour cela, en haut de la fenêtre on va aller cliquer sur le bouton &lsquo;Source Directory&rsquo; pour choisir un dossier. Généralement, ce sera un dossier d&rsquo;une solution ou d&rsquo;un projet. Une fois cela fait, on va sélectionner les fichiers via le bouton &lsquo;Select files&rsquo;. Là, on va pouvoir choisir un pattern de recherche des fichiers, qui par défaut recherche les fichier .cs. La liste des sous-dossiers va apparaître dans un TreeView à gauche tandis que les fichiers contenus dans le dossier sélectionné seront listés à droite. Il suffit de cocher un fichier pour l&rsquo;inclure dans les fichiers auxquels le header sera appliqué. A noter, une option très pratique dans le menu : &lsquo;Select all&rsquo;, &lsquo;Unselect all&rsquo;.</p>
<p>Et voilà, on peut maintenant appliquer le header aux fichiers en cliquant sur le bouton &lsquo;Go&rsquo; en bas à gauche de l&rsquo;application. Une fenêtre de log est même présente afin de savoir si le header à pu être appliqué ou non et dans le dernier cas, de savoir pourquoi.</p>
<p>L&rsquo;application propose aussi une gestion de sauvegarde et d&rsquo;ouverture de fichier .headerx, comprenant le template et la liste de correspondances des champs avec leur valeur de remplacement.</p>
<p>Téléchargement : <a href="http://code.msdn.microsoft.com/HeaderDesigner">http://code.msdn.microsoft.com/HeaderDesigner</a></p>
<p><strong>Ajouts</strong></p>
<p>Etant un peu trop limité pour mon utilisation personnelle, j&rsquo;y ai donc rajouté quelques petites choses.</p>
<p>Champs automatiques :<br />
 &#8211; Modification_Date : date de dernière modification du fichier.<br />
 &#8211; Creation_Date : date de création du fichier.<br />
 &#8211; Solution : nom de la solution si il y en a une.<br />
 &#8211; Project : nom du projet.<br />
 &#8211; Namespace : nom du namespace.<br />
 &#8211; Inherit : nom de la classe mère si il y en a une.<br />
 &#8211; Implements : nom des interfaces implémenté si il y en a.</p>
<p>Une petite aide à la saisie à aussi été intégrée dans l&rsquo;éditeur de template, pour ne pas devoir avoir la documentation sous les yeux pour ajouter un champ automatique.<br />
<img src="http://blog.developpez.com/media/AutoCompleteListBox.jpg" width="341" height="189" alt="AutoComplete ListBox" /></p>
<p>Le dossier source et les fichiers sélectionnés sont enregistrés dans le fichier .headerx, et sont donc reconnus lors de l&rsquo;ouverture du fichier.</p>
<p>L&rsquo;extension .headerx est associé à l&rsquo;application, il suffit donc d&rsquo;un double-clic sur un fichier .headerx pour l&rsquo;ouvrir avec le Code Header Designer.</p>
<p>Téléchargement :<br />
 &#8211; <a href="http://laedit.developpez.com/Storage/Applications/CodeHeaderDesigner/Code Header Designer.zip">installeur</a><br />
 &#8211; <a href="http://laedit.developpez.com/Storage/Applications/CodeHeaderDesigner/Code Header Designer - Source.zip">sources</a></p>
<p><strong>Lien</strong></p>
<p>Blog du créateur du Code Header Designer : <a href="http://colbyafrica.blogspot.com/">http://colbyafrica.blogspot.com/</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebService PHP consommé par une application C#</title>
		<link>https://blog.developpez.com/laedit/p7381/c/i_webservice_php_consomme_par_une_applic</link>
		<comments>https://blog.developpez.com/laedit/p7381/c/i_webservice_php_consomme_par_une_applic#comments</comments>
		<pubDate>Wed, 18 Mar 2009 20:57:48 +0000</pubDate>
		<dc:creator><![CDATA[laedit]]></dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Divers]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WebService]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pour créer un WebService facilement en PHP, il faut travailler en PHP5 avec l’extension SOAP d’activée. Pour cela, le mieux est de travailler en local avec Wamp Server (Wamp 5), qui permet d’activer cette extension. Une fois le matériel prêt, on va commencer par ouvrir notre éditeur de PHP préféré et d’écrire la classe qui être utilisé par le WebService. Dans notre exemple, on va juste définir une petite classe chargée de faire une opération [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Pour créer un WebService facilement en PHP, il faut travailler en PHP5 avec l’extension SOAP d’activée. Pour cela, le mieux est de travailler en local avec Wamp Server (Wamp 5), qui permet d’activer cette extension.</p>
<p><span id="more-13"></span></p>
<p>Une fois le matériel prêt, on va commencer par ouvrir notre éditeur de PHP préféré et d’écrire la classe qui être utilisé par le WebService.<br />
Dans notre exemple, on va juste définir une petite classe chargée de faire une opération et une soustraction :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">class Math <br />
{ <br />
&nbsp;<br />
&nbsp; public function Add($a, $b) <br />
&nbsp; { <br />
&nbsp; &nbsp; return $a + $b; <br />
&nbsp; } <br />
&nbsp; <br />
&nbsp; public function Substract($a, $b) <br />
&nbsp; { <br />
&nbsp; &nbsp; return $a - $b; <br />
&nbsp; } <br />
&nbsp;<br />
}</div></div>
<p>Voilà donc les méthodes qui seront exposées part le WebService.<br />
Il ne reste plus qu’à créer le serveur et la partie PHP sera terminée.<br />
 Pour cela, nous allons utiliser la classe SoapServer :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">require 'Math.class.php'; <br />
&nbsp;<br />
// première étape : désactiver le cache wsdl lors de la phase de test <br />
ini_set(&quot;soap.wsdl_cache_enabled&quot;, &quot;0&quot;); <br />
&nbsp;<br />
$wsdl &nbsp;= 'WebService.wsdl'; <br />
//Création du serveur SOAP avec le fichier WSDL <br />
$server = new SoapServer($wsdl); <br />
//Ajout de la classe Math dans les éléments proposés par le WebService <br />
$server-&gt;setClass('Math'); <br />
&nbsp;<br />
//l'utilisation du WebService se fera toujours par la méthode POST <br />
if ($_SERVER[&quot;REQUEST_METHOD&quot;] == &quot;POST&quot;) &nbsp;<br />
{ <br />
&nbsp; $server-&gt;handle(); <br />
} <br />
else //dans le cas contraire, la page affichera les méthodes proposées par le WebService <br />
{ <br />
&nbsp; echo '&lt;h4&gt;Ce serveur SOAP peut gérer les fonctions suivantes : &lt;/h4&gt;&lt;ul&gt;'; <br />
&nbsp; $functions = $server-&gt;getFunctions(); <br />
&nbsp; foreach($functions as $func) <br />
&nbsp; &nbsp; echo '&lt;li&gt;'.$func.'&lt;/li&gt;'; <br />
&nbsp; <br />
&nbsp; echo '&lt;/ul&gt;'; <br />
}</div></div>
<p>Vous avez sûrement remarqué qu’on fait appel au fichier WebService.wsdl alors qu’on ne l’a pas encore créé. On va donc s’en charger maintenant. Le mieux pour cela est d’utiliser un logiciel qui va générer le fichier wsdl finale grâce à des informations qu’on lui aura apporté. Pour ma part j’utilise Altova XML Spy qui est disponible gratuitement en version d’essai.<br />
Voilà donc ce que ça donne en version graphique :</p>
<p><img src="http://laedit.developpez.com/Storage/Articles/WSDL.jpg" alt="Résultat graphique du fichier WSDL" title="Résultat graphique du fichier WSDL" /></p>
<p>La partie serveur est à présent terminée, attaquons nous au client .net en C#.</p>
<p>L’utilisation de Visual Studio 2008 est conseillé, il permet la génération automatique d’un proxy grâce a WCF à partir du fichier WSDL.<br />
On va commencer par créer une application console. Ensuite, il suffit d’ajouter une un Service Reference en passant en adresse celle du fichier WSDL (http://localhost/WebServices/WebService.wsdl dans notre cas) et Math comme namespace pour la référence.</p>
<p>WCF a alors généré la classe MathServiceClient ainsi qu’un fichier de configuration qui vont nous servir à intéragir avec le WebService.<br />
On va instancier cette classe :</p>
<p><code class="codecolorer text default"><span class="text">MathServiceClient math = new MathServiceClient();</span></code></p>
<p>Puis on va simplement appeler nos deux méthodes :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Console.WriteLine(math.Add(5, 5)); <br />
Console.WriteLine(math.Substract(10, 5));</div></div>
<p>Et bien sûr, il ne faut pas oublier de fermer le client :</p>
<p><code class="codecolorer text default"><span class="text">math.Close();</span></code></p>
<p>Et voilà, notre client .net consomme notre WebService PHP !</p>
<p>Les sources de cet article sont disponibles <a href="http://laedit.developpez.com/Storage/Articles/WebService.rar">ici</a>.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
