<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:a10="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Paslatek Blog</title><link>http://www.paslatek.net/</link><description>This is a 'Code' blog from an bewise's employee. This blog is speaking about Microsoft's programming technologies</description><managingEditor>lionel.limozin@bewise.fr</managingEditor><category>WSS</category><category>MOSS</category><category>.Net</category><category>C#</category><category>C++</category><category>ASP.Net</category><category>Interop</category><category>COM</category><category>Crypto</category><category>Impersonation</category><category>Linq</category><category>ADO.Net</category><category>WindowsMobile</category><category>Reporting</category><category>Xml</category><category>VSTO</category><category>DirectSound</category><category>Bewise</category><category>SharePoint 2010</category><category>SharePoint Fundation</category><category>SharePoint Server</category><category>BDC</category><category>Silverlight</category><category>WCF</category><category>Silverlight Embeded</category><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/PaslatekBlog" /><feedburner:info uri="paslatekblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">73</guid><link>http://feedproxy.google.com/~r/PaslatekBlog/~3/EvWvUptO2iY/accegraves-refuseacutes-lors-de-lrsquoindexation-de-mon-sharepoint-20120404-73.aspx</link><author>lionel.limozin@bewise.fr</author><title>Accès refusés lors de l’indexation de mon SharePoint</title><description>&lt;p&gt;Je reviens sur ce Post que j’avais fait fin d’été dernier : &lt;a href="http://www.paslatek.net/accegraves-impossible-agrave-une-application-web-sharepoint-depuis-le-serveur-erreur-401-20110902-58.aspx" target="_blank"&gt;Accès impossible à une application web SharePoint depuis le serveur (erreur 401)&lt;/a&gt; / &lt;a href="http://labs.bewise.fr/kb/Acces-impossible-a-une-application-web-SharePoint-depuis-le-serveur--erreur-401-/" target="_blank"&gt;Accès impossible à une application web SharePoint depuis le serveur (erreur 401)&lt;/a&gt;     &lt;br /&gt;Pour trois raisons :     &lt;br /&gt;- Je me suis rendu compte que j’avais carrément oublié une clé registre à positionner (en tout cas d’après MSDN)     &lt;br /&gt;- mon Post n’était pas assez précis sur le format des informations à renseigner dans le registre. Je me suis fait moi même “avoir” quand j’ai été de nouveau confronté à ce problème et que j’ai suivi ma propre procédure…. qui ne fonctionnait pas.     &lt;br /&gt;- enfin j’ai rencontré ce souci ainsi qu’un collègue (quasiment en même temps, les grands esprits se rencontrent) sur le cas du moteur de recherche SharePoint dans une config de ferme “Small Farm” assez classique. Je pense qu’il est donc intéressant d’en remettre une couche sur ce cas particulier&lt;/p&gt;  &lt;p&gt;Ma ferme est donc composée de 2 frontaux, 1 serveur applicatif ayant le rôle d’indexeur (crawler) et 1 serveur SQL. J’ai aussi un loadbalancer hardware qui se charge de router les clients sur l’un ou l’autre des frontaux. A la base le serveur ayant le rôle d’indexeur se comporte comme un client final, c’est à dire que le serveur DNS lui indique que &lt;a href="http://www.intranet.fr"&gt;www.intranet.fr&lt;/a&gt; pointe sur l’IP virtuelle prise en charge par le loadbalancer. Donc chaque requête HTTP réalisée par l’indexeur est traitée par l’un ou l’autre des WFE. Dans cette configuration je n’avais pas de souci.&lt;/p&gt;  &lt;p&gt;Puis j’ai décidé de faire une configuration légèrement différente qui consiste à modifier le fichier HOST du serveur APP pour lui dire que finalement &lt;a href="http://www.intranet.fr"&gt;www.intranet.fr&lt;/a&gt; pointe sur sa propre IP. En effet le crawler est tout à fait capable de servir lui même les pages de l’intranet. Ainsi mon serveur APP travaille plus mais mes frontaux ne sont pas pénalisé par l’indexation (hormis l’impact sur le SQL Server) :&lt;/p&gt;  &lt;p align="center"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.paslatek.net/Attachments.ashx?id=133" width="682" height="462" /&gt;&lt;/p&gt;  &lt;p&gt;Et bien c’est exactement dans ce cas de figure que vous rencontrerez le même problème que moi. Le compte d’accès au contenu utilisé pour l’indexation, bien qu’ayant une “User Policy” à “Full Read'” sur votre site SharePoint va recevoir des erreur “401 Access Denied” en continu et n’arrivera plus à indexer quoique ce soit. Pour rappel les conditions à&amp;#160; réunir pour reproduire le problème:    &lt;br /&gt;- Appel http depuis le serveur sur un nom de domaine différent du nom du serveur     &lt;br /&gt;- Authentification nécessaire (en tout cas en anonyme évidement ça passe)     &lt;br /&gt;- La requête http arrive directement sur le serveur (127.0.0.1 ou une des IP du serveur)&lt;/p&gt;  &lt;p&gt;Dans ce cas, c’est IIS qui renvoi un 401, pour des raisons de sécurité au cas où vous pensiez effectivement accéder à un site externe et qu’un virus ou autre pirate aurais fait en sorte de faire tourner un site de type “pishing” sur votre serveur pour y récupérer des informations types login/password.&lt;/p&gt;  &lt;p&gt;Bref je vous redonne la procédure, complète cette fois ci.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;font size="3"&gt;- Sur le serveur en question (le crawler) ouvrez le registre        &lt;br /&gt;- Ouvrez la clé HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanmanServer\Parameters         &lt;br /&gt;- ajoutez une valeur de type DWORD avec le nom &lt;strong&gt;DisableStrictNameChecking&lt;/strong&gt; et pour valeur 1         &lt;br /&gt;- ouvrez la clé HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0         &lt;br /&gt;- ajoutez la clé de type multistring (si elle n’existe pas déjà) nommée &lt;strong&gt;BackConnectionHostNames&lt;/strong&gt;         &lt;br /&gt;- alimentez cette clé avec les noms d’hôtes à autoriser en local :         &lt;br /&gt;&amp;#160;&amp;#160; - un nom pour chaque web application à autoriser         &lt;br /&gt;&amp;#160;&amp;#160; - le nom est le nom de domaine &lt;strong&gt;SANS le protocole&lt;/strong&gt;, par exemple : intranet.fr (et pas &lt;/font&gt;&lt;/em&gt;&lt;a href="http://www.intranet.fr"&gt;&lt;em&gt;&lt;font size="3"&gt;http://www.intranet.fr&lt;/font&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="3"&gt;) ou encore app1.domaine.com (et pas &lt;/font&gt;&lt;a href="http://app1.domaine.com"&gt;&lt;font size="3"&gt;http://app1.domaine.com&lt;/font&gt;&lt;/a&gt;&lt;font size="3"&gt;)        &lt;br /&gt;- Redémarrez le service IISADMIN&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Sources : &lt;a title="http://support.microsoft.com/kb/896861/en-us" href="http://support.microsoft.com/kb/896861/en-us"&gt;http://support.microsoft.com/kb/896861/en-us&lt;/a&gt; et &lt;a title="http://support.microsoft.com/kb/281308" href="http://support.microsoft.com/kb/281308"&gt;http://support.microsoft.com/kb/281308&lt;/a&gt;&lt;/p&gt;</description><pubDate>Wed, 04 Apr 2012 09:10:01 +0200</pubDate><a10:updated>2012-04-04T09:10:01+02:00</a10:updated><feedburner:origLink>http://www.paslatek.net/accegraves-refuseacutes-lors-de-lrsquoindexation-de-mon-sharepoint-20120404-73.aspx</feedburner:origLink></item><item><guid isPermaLink="false">72</guid><link>http://feedproxy.google.com/~r/PaslatekBlog/~3/xwfxkWDfDx0/suivez-moi-sur-twitter-20120311-72.aspx</link><author>lionel.limozin@bewise.fr</author><title>Suivez moi sur Twitter</title><description>&lt;p&gt;Mieux vaux tard que jamais pour se mettre aux technos 2.0 &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Clignement d&amp;#39;œil" src="http://www.paslatek.net/Attachments.ashx?id=132" /&gt;. Donc voilà ça c’est fait et c’est ici que ça ce passe : &lt;a class="twitter-follow-button" href="https://twitter.com/LimozinLionel" data-lang="fr" data-show-count="false"&gt;Suivre @LimozinLionel&lt;/a&gt; &lt;script&gt;!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");&lt;/script&gt;&lt;/p&gt;</description><pubDate>Sun, 11 Mar 2012 13:11:36 +0100</pubDate><a10:updated>2012-03-11T13:11:36+01:00</a10:updated><feedburner:origLink>http://www.paslatek.net/suivez-moi-sur-twitter-20120311-72.aspx</feedburner:origLink></item><item><guid isPermaLink="false">71</guid><link>http://feedproxy.google.com/~r/PaslatekBlog/~3/dfp6nDxjqqs/webcasts-techdays-2012-20120309-71.aspx</link><author>lionel.limozin@bewise.fr</author><title>Webcasts Techdays 2012</title><description>&lt;p&gt;&lt;img title="image" border="0" alt="image" align="left" src="http://www.paslatek.net/Attachments.ashx?id=129" width="233" height="89" /&gt; Les Webcast des Techdays 2012 sont en ligne ! Vous pouvez les retrouver tous ici&amp;#160; : &lt;a title="http://www.microsoft.com/france/mstechdays/programmes/parcours.aspx#&amp;amp;fbid=6Ru1UeiZP86" href="http://www.microsoft.com/france/mstechdays/programmes/parcours.aspx#&amp;amp;fbid=6Ru1UeiZP86"&gt;http://www.microsoft.com/france/mstechdays/programmes/parcours.aspx#&amp;amp;fbid=6Ru1UeiZP86&lt;/a&gt;. Concernant la session que j’ai animé avec Alain Marty voici un lien direct : &lt;a title="http://www.microsoft.com/fr-fr/showcase/details.aspx?uuid=d6d73a39-a080-42e9-b87a-03ff2b025660" href="http://www.microsoft.com/fr-fr/showcase/details.aspx?uuid=d6d73a39-a080-42e9-b87a-03ff2b025660"&gt;http://www.microsoft.com/fr-fr/showcase/details.aspx?uuid=d6d73a39-a080-42e9-b87a-03ff2b025660&lt;/a&gt;&lt;/p&gt;</description><pubDate>Fri, 09 Mar 2012 09:38:45 +0100</pubDate><a10:updated>2012-03-09T09:38:45+01:00</a10:updated><feedburner:origLink>http://www.paslatek.net/webcasts-techdays-2012-20120309-71.aspx</feedburner:origLink></item><item><guid isPermaLink="false">70</guid><link>http://feedproxy.google.com/~r/PaslatekBlog/~3/Vpbsav9rkr8/techdays-2012-ou-lrsquoanneacutee-des-12-sessions-sharepoint-20120202-70.aspx</link><author>lionel.limozin@bewise.fr</author><title>Techdays 2012 ou l’année des 12 sessions SharePoint</title><description>&lt;p&gt;Cette Année SharePoint tiens encore une place importante aux Techdays. Pas moins de 12 Sessions ! &lt;a href="http://blogs.msdn.com/b/sharepointfrance/archive/2012/01/30/sharepoint-une-place-d-honneur-aux-techdays-2012-mstechdays.aspx" target="_blank"&gt;Retrouvez ici&lt;/a&gt; un détail complet. Bien sûr vous devez privilégier &lt;a href="http://www.microsoft.com/france/mstechdays/programmes/parcours.aspx#SessionID=7ae20379-9c2c-4303-b309-938431428fc0&amp;amp;fbid=tT72wxFA09Q" target="_blank"&gt;ma session&lt;/a&gt; &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Clignement d&amp;#39;œil" src="http://www.paslatek.net/Attachments.ashx?id=131" /&gt;&lt;/p&gt;</description><pubDate>Thu, 02 Feb 2012 15:02:28 +0100</pubDate><a10:updated>2012-02-02T15:02:28+01:00</a10:updated><feedburner:origLink>http://www.paslatek.net/techdays-2012-ou-lrsquoanneacutee-des-12-sessions-sharepoint-20120202-70.aspx</feedburner:origLink></item><item><guid isPermaLink="false">69</guid><link>http://feedproxy.google.com/~r/PaslatekBlog/~3/irRv_8CVm4I/rejoignez-moi-aux-techdaysrsquo12-20120127-69.aspx</link><author>lionel.limozin@bewise.fr</author><title>Rejoignez moi aux Techdays’12</title><description>&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://www.paslatek.net/Attachments.ashx?id=129" width="233" height="89" /&gt;Information de dernière minute ! Je serais finalement speaker aux Techdays de cette année ! Bien sûr le sujet est SharePoint. Cette année on va la jouer “gentil” et donc pas de Dev ! juste une bonne session de découverte sur les aspect GED de SharePoint 2010.     &lt;br /&gt;---&amp;gt;&amp;#160; &lt;a href="http://www.microsoft.com/france/mstechdays/programmes/parcours.aspx#SessionID=7ae20379-9c2c-4303-b309-938431428fc0&amp;amp;fbid=tT72wxFA09Q" target="_blank"&gt;&lt;strong&gt;Le détail ici&lt;/strong&gt;&lt;/a&gt; &amp;lt;--- .     &lt;br /&gt;Je serais aussi présent aux stands “Ask the expert” sur la partie “efficacité individuelle et collective” le Mardi 7 et Mercredi 8 février. N’hésitez pas à venir me passer un p’tit bonjour &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Clignement d&amp;#39;œil" src="http://www.paslatek.net/Attachments.ashx?id=130" /&gt;&lt;/p&gt;</description><pubDate>Fri, 27 Jan 2012 13:56:35 +0100</pubDate><a10:updated>2012-01-27T13:56:35+01:00</a10:updated><feedburner:origLink>http://www.paslatek.net/rejoignez-moi-aux-techdaysrsquo12-20120127-69.aspx</feedburner:origLink></item><item><guid isPermaLink="false">68</guid><link>http://feedproxy.google.com/~r/PaslatekBlog/~3/2YFKR2c8tX8/mvp-sharepoint-server-20120102-68.aspx</link><author>lionel.limozin@bewise.fr</author><title>MVP SharePoint Server</title><description>&lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="Microsoft_MVP_logo" border="0" alt="Microsoft_MVP_logo" align="left" src="http://www.paslatek.net/Attachments.ashx?id=128" width="64" height="98" /&gt;Pour bien commencer l’année j’ai eu le grand plaisir et honneur d’être nommé MVP ( c’est une première pour moi ! &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Sourire" src="http://www.paslatek.net/Attachments.ashx?id=127" /&gt; ) et ceci pour récompenser mes diverses participations au sein de la communauté, française, SharePoint Server. Bien sûr je vais faire en sorte de bien défendre ce titre tout au long de l’année en continuant à partager au maximum mes trucs, astuces, retours d’expériences, etc. sur ce blog. Donc comme on dit : “Stay Tuned !”&lt;/p&gt;</description><pubDate>Mon, 02 Jan 2012 16:01:39 +0100</pubDate><a10:updated>2012-01-02T16:01:39+01:00</a10:updated><feedburner:origLink>http://www.paslatek.net/mvp-sharepoint-server-20120102-68.aspx</feedburner:origLink></item><item><guid isPermaLink="false">67</guid><link>http://feedproxy.google.com/~r/PaslatekBlog/~3/et5TjMAkzZo/la-reacuteussite-de-vos-projets-sharepoint-passe-par-une-inteacutegration-continue-20111121-67.aspx</link><author>lionel.limozin@bewise.fr</author><title>La réussite de vos projets SharePoint passe par une intégration continue</title><description>&lt;p&gt;&lt;img style="margin: 0px 10px 0px 0px; display: inline; float: left" alt="" align="left" src="http://images.discountasp.net/tfs-newsletter/2011-06/tfsBuildlogo.png" width="82" height="82" /&gt;Connaissez-vous l'intégration continue ? Avez-vous des doutes sur ses intérêts et avantages ? Je ne chercherais pas à répondre à ces questions dans cet article car vous en trouverez certainement des dizaines voire même des centaines bien plus pertinents que le mien. Malgré tout, afin de planter un minimum le décor, voici pour faire simple la définition de Wikipédia :&lt;/p&gt;  &lt;p&gt;&lt;a href="http://fr.wikipedia.org/wiki/Int%C3%A9gration_continue"&gt;« L'intégration continue est un ensemble de pratiques utilisées en génie logiciel. Elles consistent à vérifier à chaque modification de code source que le résultat des modifications ne produit pas de régression de l'application en cours de développement. »&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Par contre, une fois que vous aurez fait ces recherches, je ne doute pas que vous soyez au moins autant convaincu que moi. Alors peut-être à ce moment vous vous demanderez : « Comment mettre en place ce type de processus d'intégration continue avec des projets SharePoint ? ». Dans ce cas, cet article est pour vous !&lt;/p&gt;  &lt;p&gt;Je vais vous guider sur les outils à utiliser et comment les utiliser pour mettre en place une compilation, un déploiement et des tests, tout ceci de manière automatique, pour vos projets dédiés à la plateforme SharePoint 2010.&lt;/p&gt;  &lt;p&gt;Ce processus fera appel à la plateforme Team Foundation Server, en particulier l'aspect &amp;quot;Build&amp;quot; automatique permettant de séquencer un ensemble d'actions telles que « compilation », « exécution de processus externe », « création de WorkItems », « exécution de tests unitaires ».&lt;/p&gt;  &lt;p&gt;Retrouvez l’article complet sur &lt;a href="http://labs.bewise.fr" target="_blank"&gt;labs.bewise.fr&lt;/a&gt; : &lt;a href="http://labs.bewise.fr/Article/La-reussite-de-vos-projets-SharePoint-passe-par-une-integration-continue--Part-1-2-/" target="_blank"&gt;&lt;strong&gt;Partie 1&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; et &lt;/strong&gt;&lt;a href="http://labs.bewise.fr/Article/la-r%C3%A9ussite-de-vos-projets-sharepoint-passe-par-une-int%C3%A9gration-continue-part-2-2/" target="_blank"&gt;&lt;strong&gt;Partie 2&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 21 Nov 2011 11:53:37 +0100</pubDate><a10:updated>2011-11-21T11:53:37+01:00</a10:updated><feedburner:origLink>http://www.paslatek.net/la-reacuteussite-de-vos-projets-sharepoint-passe-par-une-inteacutegration-continue-20111121-67.aspx</feedburner:origLink></item><item><guid isPermaLink="false">66</guid><link>http://feedproxy.google.com/~r/PaslatekBlog/~3/zcEISsTvkmY/le-getter-de-la-mort-20111118-66.aspx</link><author>lionel.limozin@bewise.fr</author><title>Le getter de la mort</title><description>&lt;p&gt;Nous utilisons très souvent des propriétés public sur des classes, que ce soit en get ou set. SharePoint et son SDK ni manque pas non plus. Cependant méfiez vous de certains pièges où on pense que le getter ne renvoi qu’une variable interne ! ce n’est pas toujours vrai ! Le getter peu faire beaucoup de chose avant de vous renvoyer le résultat… Les performances de votre application peuvent donc en pâtir, mais vous pouvez carrément avoir des “bugs”. Un bon exemple avec le SPWeb.RootFolder :&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Scénario : &lt;/strong&gt;Vous devez modifier la WelcomePage d’un SPWeb par code. Par défaut on aurait tendance à faire ça :&lt;/p&gt;  &lt;p&gt;SPWeb w = ….. // je ne m’attarde pas sur la récupération du SPWeb&lt;/p&gt;  &lt;p&gt;w.RootFolder.WelcomePage = “toto.aspx”&lt;/p&gt;  &lt;p&gt;w.RootFolder.Update();&lt;/p&gt;  &lt;p&gt;Comme beaucoup de classes dans le SDK de SharePoint, il faut appeler la méthode Update pour valider la mise à jour. Mais il se trouve que ça ne marche pas ! (pas de plantage mais la page d’accueil ne sera pas changée) pourquoi ? Regardons l’implémentation de RootFolder avec Reflector :&lt;/p&gt;  &lt;p&gt;public &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Microsoft.SharePoint:14.0.0.0:71e9bce111e9429c/Microsoft.SharePoint.SPFolder"&gt;SPFolder&lt;/a&gt; &lt;b&gt;&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Microsoft.SharePoint:14.0.0.0:71e9bce111e9429c/Microsoft.SharePoint.SPWeb/property:RootFolder:Microsoft.SharePoint.SPFolder"&gt;RootFolder&lt;/a&gt;&lt;/b&gt; { get { return new &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Microsoft.SharePoint:14.0.0.0:71e9bce111e9429c/Microsoft.SharePoint.SPFolder/.ctor(Microsoft.SharePoint.SPWeb,String)"&gt;SPFolder&lt;/a&gt;(this, &amp;quot;&amp;quot;); } }&lt;/p&gt;  &lt;p&gt;Et oui ! une nouvelle instance à chaque fois ! du coup l’appel à Update n’est pas fait sur la même instance de SPFolder et on perd donc la modification de la WelcomePage. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution&amp;#160; : &lt;/strong&gt;Dans ce cas il faut faire ça :&lt;/p&gt;  &lt;p&gt;SPFolder f = w.RootFolder;&lt;/p&gt;  &lt;p&gt;f.WelcomePage = “toto.aspx”&lt;/p&gt;  &lt;p&gt;f.Update();&lt;/p&gt;  &lt;p&gt;Et le tour est joué !&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Conclusion :&lt;/strong&gt; ne soyons pas trop flemmard à déclarer des variables intermédiaires…&lt;/p&gt;</description><pubDate>Fri, 18 Nov 2011 08:31:28 +0100</pubDate><a10:updated>2011-11-18T08:31:28+01:00</a10:updated><feedburner:origLink>http://www.paslatek.net/le-getter-de-la-mort-20111118-66.aspx</feedburner:origLink></item><item><guid isPermaLink="false">65</guid><link>http://feedproxy.google.com/~r/PaslatekBlog/~3/G_-hZxR5atQ/problegraveme-sur-le-cumulative-update-octobre-pour-moss-2007-sp3-20111104-65.aspx</link><author>lionel.limozin@bewise.fr</author><title>Problème sur le Cumulative Update Octobre pour MOSS 2007 SP3</title><description>&lt;p&gt;Attention à ceux qui souhaiterais installer le CU d’octobre sur un MOSS 2007 ! si votre Moss est déjà en SP3 ça ne sera pas possible !… &lt;a title="http://blogs.technet.com/b/stefan_gossner/archive/2011/10/29/be-careful-when-planning-to-install-moss-2007-october-2011-cu-and-service-pack-3.aspx" href="http://blogs.technet.com/b/stefan_gossner/archive/2011/10/29/be-careful-when-planning-to-install-moss-2007-october-2011-cu-and-service-pack-3.aspx"&gt;http://blogs.technet.com/b/stefan_gossner/archive/2011/10/29/be-careful-when-planning-to-install-moss-2007-october-2011-cu-and-service-pack-3.aspx&lt;/a&gt;. Il semble qu’il faille installer ce CU avant le SP3. Et pour ceux qui ont déjà le SP3 … pas de solution ?&lt;/p&gt;</description><pubDate>Fri, 04 Nov 2011 09:27:52 +0100</pubDate><a10:updated>2011-11-04T09:27:52+01:00</a10:updated><feedburner:origLink>http://www.paslatek.net/problegraveme-sur-le-cumulative-update-octobre-pour-moss-2007-sp3-20111104-65.aspx</feedburner:origLink></item><item><guid isPermaLink="false">64</guid><link>http://feedproxy.google.com/~r/PaslatekBlog/~3/TFeSNG941ok/spcontext-et-spservicecontext-dans-le-mauvais-contexte-ou-le-piegravege-du-singleton-masqueacute-20111102-64.aspx</link><author>lionel.limozin@bewise.fr</author><title>SPContext et SPServiceContext dans le mauvais Contexte ou le piège du singleton masqué</title><description>&lt;p&gt;Sous couvert de ce titre en jeux de mots je souhaite vous parler d’un sujet inspiré de deux problèmes rencontrés avec du code pour SharePoint.    &lt;br /&gt;&lt;em&gt;(EDIT 18/11/2011 : J’ai modifié mon code car j’utilisais le Thread.CurrentPrincipal pour assigner le User du HttpContext. Dans le cas d’une application console, ce CurrentPrincipal est “vide”. J’ai donc corrigé pour utiliser “new WindowsPrincipal(WindowsIdentity.GetCurrent())” à la place)&lt;/em&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;h3&gt;1 - L’erreur de départ&lt;/h3&gt;  &lt;p&gt;Concrètement ces deux “erreurs” apparaissent dans un contexte particulier qui est celui d’une application Windows (batch, powershell, client lourd) utilisant le SDK de SharePoint :&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;1er cas&lt;/strong&gt; : c’est la cas “facile”. En tentant de construire une instance de UserProfileManager vous utilisez la ligne de code suivante :&lt;/p&gt;  &lt;p&gt;UserProfileManager mana = new UserProfileManager(SPServiceContext.Current);&lt;/p&gt;  &lt;p&gt;et vous obtenez l’exception suivante :&lt;/p&gt;  &lt;p&gt;&lt;em&gt;System.ArgumentNullException : Value cannot be null. Parameter name: serviceContext&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;at Microsoft.Office.Server.UserProfiles.ProfileManagerBase..ctor(SPServiceContext serviceContext)      &lt;br /&gt;at Microsoft.Office.Server.UserProfiles.ProfileManagerBase..ctor(SPServiceContext serviceContext, Boolean ignorePrivacy)       &lt;br /&gt;at Microsoft.Office.Server.UserProfiles.UserProfileManager..ctor(SPServiceContext serviceContext, Boolean IgnoreUserPrivacy, Boolean backwardCompatible)       &lt;br /&gt;at Microsoft.Office.Server.UserProfiles.UserProfileManager..ctor(SPServiceContext serviceContext, Boolean IgnoreUserPrivacy)       &lt;br /&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2nd cas :&lt;/strong&gt; c’est la cas “vicieux”. En utilisant un SPLimitedWebPartManager pour modifier ou consulter les propriétés de webparts, en particulier des ContentByQueryWebPart ayant des XSLT customs attachés (ItemXslLink et/ou MainXslLink) vous récupérez uniquement des Microsoft.SharePoint.WebPartPages.ErrorWebPart avec comme erreur par exemple : &lt;/p&gt;  &lt;p&gt;&lt;em&gt;An error occurred while setting the value of this property: Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart:ItemXslLink - Exception has been thrown by the target of an invocation.&lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;2 – L’analyse&lt;/h3&gt;  &lt;p&gt;Alors bien sûr vous vous en doutez, la raison est globalement la même, il s’agit du context qui est mal initialisé car nous sommes dans un contexte client lourd et pas application web, c’est logique…&lt;/p&gt;  &lt;p&gt;Mais quel contexte ? SPServiceContext, SPContext, HttpContext ? &lt;/p&gt;  &lt;p&gt;Et puis d’abord comme ça se fait que le singleton SPContext.Current ne se débrouille pas tout seul pour être correctement construit&amp;#160; ?!&lt;/p&gt;  &lt;p&gt;Instinctivement j’aurais tendance à dire que le SPServiceContext.Current utilise le SPContext.Current qui à son tour utilise le HttpContext.Current. Vérifions avec une bonne vielle décompilation :&lt;/p&gt;  &lt;p&gt;SPServiceContexT.Current:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:1cd63ed7-628c-4de4-9976-0a5c0ebce446" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public static SPServiceContext Current 
{ 
    get 
    { 
        SPServiceContextScope currentScope = SPServiceContextScope.CurrentScope; 
        if (currentScope != null) 
        { 
            return currentScope.Context; 
        } 
        return GetContext(HttpContext.Current); 
    } 
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;et SPContext.Current :&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ba2cb0f1-4b4a-4b91-a150-b729910be0c5" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public static SPContext Current 
{ 
    get 
    { 
        SPContext context = null; 
        if (HttpContext.Current != null) 
        { 
            try 
            { 
                if (SPControl.GetContextWeb(HttpContext.Current) == null) 
                { 
                    return null; 
                } 
            } 
            catch (InvalidOperationException) 
            { 
                return null; 
            } 
            try 
            { 
                context = GetContext(HttpContext.Current); 
            } 
            catch (FileNotFoundException) 
            { 
            } 
            catch (InvalidOperationException) 
            { 
            } 
        } 
        return context; 
    } 
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On constate que dans les deux cas il faut que le HttpContext.Current soit initialisé. Sur la cas du SPContext c’est d’autant plus flagrant qu’un premier test vérifie que le HttpContext fourni n’est pas null.&lt;/p&gt;

&lt;p&gt;Du coup cette imbrication de propriétés, toutes statiques, masquent un peu un besoin nécessaire au bon fonctionnement des classes du SDK : un contexte d’application web, donc une requête http sur une url. Quelque part cela ne me “choque pas” sur le principe que SharePoint est avant tout utilisé dans un contexte web. Donc l’utiliser dans un autre contexte peut nécessiter des actions supplémentaires. Ce qui me gène c’est que dans certains cas, l’utilisation du SPContext est faite en interne par le biais d’autres classes et méthodes et dans mon cas la remontée d’erreur n’est pas forcement très explicite. &lt;/p&gt;

&lt;p&gt;Par exemple ma seconde erreur est due au fait que j’utilise un ContentByQueryWebPart qui lui même hérite d’un CmsDataFormWebPart qui notamment dans le cas du setter de certaines propriétés (comme celle concernant le Xsl) appelle une méthode nommée MakeSiteRelativeUrl.&lt;/p&gt;

&lt;p&gt;Que fait cette méthode ? Je vous le donne en mille :&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:3fe76192-bca6-48a9-a855-985a9335ba26" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;private static string MakeSiteRelativeUrl(string xslServerRelativeUrl) 
{ 
    string serverRelativeUrl = SPContext.Current.Site.ServerRelativeUrl; 
...
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Et évidement si je n’ai pas de HttpContext, je n’ai pas non plus de SPContext, et donc pas de Site et encore moins de ServerRelativeUrl.&lt;/p&gt;

&lt;p&gt;Et pour finir, lors de l’analyse de la page par le SPLimitedWebPartManager, le webpart est chargé comme si il était rendu dans la page web, donc le XslLink est fixé lors du CreateChildControl et donc en cascade la fameuse méthode est appelée, elle plante, SharePoint prends ça en charge et remplace le webpart par un ErrorWebPart…&lt;/p&gt;

&lt;h3&gt;3 – La résolution&lt;/h3&gt;

&lt;p&gt;La solution est simple me diriez vous ! Il suffit d’instancier un HttpContext dans le cas d’une application qui ne tournera pas en application web ! Ok très bien allons y. Pour instancier un HttpContext il nous faut une HttpRequest qui a besoin d’une url et d’une HttpResponse.&lt;/p&gt;

&lt;p&gt;Concernant l’url il me semble judicieux de fournir celle du SPWeb que l’on souhaite ouvrir ou du SPFile par exemple, je rajoute donc la ligne suivante juste après l’ouverture d’un SPWeb nommé web :&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:35325513-b5dd-4130-a2cc-5eb6af2b145e" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;HttpContext.Current = new HttpContext(new HttpRequest("", web.Url, ""), new HttpResponse(new StringWriter()));&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Et malheureusement ça ne suffit pas !&lt;/p&gt;

&lt;p&gt;Et pour comprendre pourquoi le mieux et de retourner voir le code de la propriété SPContext.Current, en particulier la méthode SPControl.GetContextWeb :&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:be07282d-48a4-42ea-b6bc-ab1c56d24538" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;private static SPWeb SPWebEnsureSPControl(HttpContext context) 
{ 
   SPWeb web = (SPWeb) context.Items["HttpHandlerSPWeb"]; 
    if ((web == null) &amp;amp;&amp;amp; (context.Items["HttpHandlerSPSiteNotFound"] == null)) 
    { 
        if (context.User == null) 
        { 
            context.Items["HttpHandlerSPSiteNotFound"] = "1"; 
            throw new InvalidOperationException(); 
        } 
        if (SPSecurity.ImpersonatingSelf || SPSecurity.RunAsUserInProgress) 
        { 
            throw new InvalidOperationException(); 
        } 
        try 
        { 
            SPSite site; 
            context.Items["HttpHandlerSPSite"] = site = SPSiteFromContextNoCache(); 
            if (site == null) 
            { 
                context.Items["HttpHandlerSPSiteNotFound"] = "1"; 
                return null; 
            } 
            web = site.OpenWeb(); 
            context.Items["HttpHandlerSPWeb"] = web; 
            if (!SPRequestUsageMonitoredScope.s_FirstBrowseHasOccured) 
            { 
                SPRequestUsageMonitoredScope.s_FirstBrowseHasOccured = true; 
            } 
            if (SPSecurity.ApplicationPrincipal == null) 
            { 
                site.InitUserToken(EnsureSPWebRequest(web)); 
            } 
            else 
            { 
                site.InitUserToken(null); 
            } 
            SPRequestModule.InitContextWeb(context, web); 
            if (SPContext.GetShouldInitThreadCultureWhenContextWebIsInited(context)) 
            { 
                web.SetThreadCultureAfterInit(); 
            } 
            ULS.CorrelationAdd("Site", site.ServerRelativeUrl); 
        } 
        catch (FileNotFoundException) 
        { 
            context.Items["HttpHandlerSPSiteNotFound"] = "1"; 
        } 
    } 
    return web; 
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A mon sens il y a dans cette méthode deux choses importantes à ne pas louper :&lt;/p&gt;

&lt;p&gt;1- on essai d’abord de récupérer un SPWeb à partir d’un Item du HttpContext nommé “HttpHandlerSPWeb”&lt;/p&gt;

&lt;p&gt;2- si cet SPWeb n’est pas présent, on tente de le créer, mais à condition notamment d’avoir un User sur le HttpContext courant. A défaut on recevra une InvalidOperationException.&lt;/p&gt;

&lt;p&gt;le SPWeb quand à lui sera crée à partir du SPSite crée lui même à partir d’une méthode SPSiteFromContextNoCache qui au final va chercher une url dans le HttpContext sous l’Item “Microsoft.SharePoint.Administrtion.ContextUri&amp;quot;, qui dans notre cas n’est très probablement pas renseignée.&lt;/p&gt;

&lt;p&gt;Je vais donc rajouter deux lignes de codes supplémentaire juste après l’ouverture de mon SPWeb pour initialiser correctement le HttpContext:&lt;/p&gt;

&lt;p&gt;Pour être sûr que le SPWeb puisse être construit dans le SPContext :&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:5ea59d5f-6084-4d86-a411-ba94b7696c3c" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;HttpContext.Current.User =  new WindowsPrincipal(WindowsIdentity.GetCurrent()); &lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Tant qu’à faire, ayant déjà un SPWeb sous la main, pour gagner du temps :&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:da1e4571-ff7d-4181-b3ce-99b1aa167d9e" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;HttpContext.Current.Items["HttpHandlerSPWeb"] = web;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Bien sûr cela n’est pas du tout conseillé dans un contexte web, donc à ne &lt;strong&gt;PAS&lt;/strong&gt; &lt;strong&gt;faire systématiquement&lt;/strong&gt;, mais bien dans le cas précis d’une application qui est exécutée sur le serveur, avec une identité “choisie”.&lt;/p&gt;

&lt;p&gt;Avec ces 3 lignes de codes, mon application console fonctionne à merveille !&lt;/p&gt;

&lt;p&gt;Pour me simplifier un peu la vie, j’ai crée quelques extensions de méthodes :&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:52bf6383-8d61-44d0-94bd-d1e0ab6705ce" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public static class SPSiteExtensions
{
	public static void EnsureContext(this SPSite site)
	{
	    if (HttpContext.Current == null)
	    {
	        HttpContext.Current = new HttpContext(new HttpRequest("", site.Url, ""), new HttpResponse(new StringWriter()));
	        //en principe suffisant
	        HttpContext.Current.User =  new WindowsPrincipal(WindowsIdentity.GetCurrent());
	    }
	}
}
public static class SPWebExtensions
{
    public static void EnsureContext(this SPWeb web)
    {
        if (HttpContext.Current == null)
        {
            HttpContext.Current = new HttpContext(new HttpRequest("", web.Url, ""), new HttpResponse(new StringWriter()));
            //en principe suffisant
            HttpContext.Current.User =  new WindowsPrincipal(WindowsIdentity.GetCurrent());
            //pour gagner du temps
            HttpContext.Current.Items["HttpHandlerSPWeb"] = web;
        }
    }
    public static SPWeb OpenWeb(this SPSite site,bool loadHttpContext)
    {
        SPWeb w = site.OpenWeb();
        if (w == null) return null;
        w.EnsureContext();
        return w;
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Et l’utilisation est du coup assez simple :&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:a5bccc4b-26b6-4777-92f1-56ed52b47662" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;static void Main(string[] args)
{
    string url = "http://root.paslatek.com/SitePages/testCQWP.aspx";
    using (SPSite site = new SPSite(url))
    {
        //première façon de faire si on va pas plus loin que le SPSite
        site.EnsureContext();
   //ouverture SPWeb avec la metode d'extension
        using (SPWeb web = site.OpenWeb(true))
        {

            //autre manière d'assurer le context avec le SPWeb
            web.EnsureContext();
           ////test 1
            UserProfileManager mana = new UserProfileManager(SPServiceContext.Current, true);
            foreach (UserProfile u in mana)
                Console.WriteLine(u.DisplayName);
            //test 2
            SPFile f = web.GetFile(url);
            var wpMana = f.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
            foreach (System.Web.UI.WebControls.WebParts.WebPart wp in wpMana.WebParts)
                Console.WriteLine(wp.GetType().ToString());
        }
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;4 – La conclusion&lt;/h3&gt;

&lt;p&gt;Le SPContext.Current c’est le mal ? Il ne faut pas l’utiliser ? &lt;/p&gt;

&lt;p&gt;De manière générale j’ai envie de dire oui, pour vous éviter ce genre de cas tordu où par un enchainement d’appels, à travers un tas de classes, vous arriviez sur un cas identique au mien. En effet dans mon cas, les codes utilisant le UserProfileManager et du SPLimitedWebPartManager étaient dans le un FeatureReceiver, à l’activation de la feature. Ce code à très bien fonctionné tant qu’on activait la feature par l’interface web. Jusqu’au jour où j’ai eu besoin d’utiliser une application console qui parcourais un bon millier de sites et activait la feature en question de manière automatique. E là c’est le drame !&lt;/p&gt;

&lt;p&gt;Mais au final de toute façon tout cela ne dépends pas que de vous, puisque comme nous l’avons vu, certains composants de ce, riche, Framework qu’est SharePoint utilisent eux mêmes le SPContext. De plus j’ai rencontré ici deux cas particuliers, mais rien ne dit que vous ne tomberez pas sur un autre problème dont la source est la même sur d’autres webparts par exemple. Donc vous n’y pourrez pas grand chose d’autre que d’utiliser un contournement comme celui que je vous ai proposé dans cet article.&lt;/p&gt;

&lt;p&gt;Ce qui est marrant c’est que &lt;a href="http://msdn.microsoft.com/en-us/library/ms468609.aspx" target="_blank"&gt;la documentation MSDN&lt;/a&gt; est assez claire sur le sujet, entre autre parce qu'elle dit bien que le SPContext n’a pas de sens dans le cas d’une application console…&lt;/p&gt;

&lt;p&gt;Merci aussi à SanDeep pour &lt;a href="http://sharepoint-insight.blogspot.com/2008/10/sharepoint-all-webparts-appear-as.html" target="_blank"&gt;son article sur le SPLimitedWebPartManager et la création du HttpContext&lt;/a&gt;&lt;/p&gt;</description><pubDate>Wed, 02 Nov 2011 09:13:13 +0100</pubDate><a10:updated>2011-11-02T09:13:13+01:00</a10:updated><feedburner:origLink>http://www.paslatek.net/spcontext-et-spservicecontext-dans-le-mauvais-contexte-ou-le-piegravege-du-singleton-masqueacute-20111102-64.aspx</feedburner:origLink></item></channel></rss>

