tag:blogger.com,1999:blog-281488112024-03-13T19:01:56.181+01:00Jonathan's IT Blog - Sharing PointersMostly SharePoint stuff but some general IT stuff as well<br>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.comBlogger50125tag:blogger.com,1999:blog-28148811.post-61589295259053282782013-06-15T19:22:00.000+02:002013-06-15T23:06:51.110+02:00Scroll Gantt view to today in SharePoint 2010 & 2013<b>Abstract</b>, here is a trick to have the SharePoint Gantt view displayed scolled to today instead of the first day of the earliest task. Tested on SharePoint 2010 & SharePoint 2013. Here comes the trick and how it was found<br />
<br />
SharePoint Gantt views are a great tool to visualy embrace a set of data\dates but they suffer from a few usability issue. First one is that Gantt view <b>always center on the earliest date</b> of the tasks displayed. This is often an issue if you display projects spanning multiple months or year as you don’t see today’s situation :<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-MRqXYzrAlHs/UbyhR79h0TI/AAAAAAAATmE/69ba4k2B6RM/s1600/image007.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Default SharePoint Gantt view centers on the earliest date" border="0" height="81" src="http://1.bp.blogspot.com/-MRqXYzrAlHs/UbyhR79h0TI/AAAAAAAATmE/69ba4k2B6RM/s400/image007.jpg" title="Default SharePoint Gantt view centers on the earliest date" width="400" /></a></div>
<br />
<br />
We decided to fix it. Our first stop was to take a look at SharePoint out of the box SPGantt.js file (SPGantt.debug.js for convenience), where best to find out what was possible. Searching for scroll brought up a few reference including this very promising one :<br />
<br />
<pre> this.ScrollGanttToTask=function()
….
_jsGridControl.ScrollGanttToDate(date);
….
</pre>
<br />
Next step was to manage to get an handle on this jsGridControl object. Fiddling through the DOM with Google Chrome (Elements and console tabs) we found out the *_ListViewWebPartJSGrid object had a nice jsgrid property that returns the object we need<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-lrAntHAFX0Q/UbyheypGiII/AAAAAAAATmM/za70Wvco7mc/s1600/image004.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-lrAntHAFX0Q/UbyheypGiII/AAAAAAAATmM/za70Wvco7mc/s1600/image004.png" /></a></div>
<br />
And this object indeed have a ScrollGanttToDate function<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-m5zGBelOmYQ/UbyhhImaLjI/AAAAAAAATmU/6pclp0u9bFE/s1600/image005.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-m5zGBelOmYQ/UbyhhImaLjI/AAAAAAAATmU/6pclp0u9bFE/s1600/image005.png" /></a></div>
<br />
If you use jQuery here is how to retrieve the object and scroll to today. Depending how\where you use it, you might want to make sure the object exists (if($("div [id$='_ListViewWebPartJSGrid']").length) ) before using the property jsGrid.<br />
<br />
<blockquote class="tr_bq">
<span style="color: #783f04; font-size: large;"><b>$("div [id$='_ListViewWebPartJSGrid']")[0].jsgrid.ScrollGanttToDate(new Date()) </b></span></blockquote>
<br />
Tada !<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-oMq_dzoci7k/Ubyhjy_GEOI/AAAAAAAATmc/vi1TSB_rJDA/s1600/image011.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="SharePoint Gantt view centered on today's date" border="0" height="85" src="http://3.bp.blogspot.com/-oMq_dzoci7k/Ubyhjy_GEOI/AAAAAAAATmc/vi1TSB_rJDA/s400/image011.jpg" title="SharePoint Gantt view centered on today's date" width="400" /></a></div>
<br />Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com19tag:blogger.com,1999:blog-28148811.post-375556263093341832013-02-15T18:51:00.001+01:002013-02-15T18:59:13.832+01:00SharePoint 2010, power up your tags by making them clickable<div align="justify">
SharePoint 2010 introduced a great new feature that is used even more in SharePoint 2013, the tags. A major drawback of tags is that they are not clickable except in very specific scenario.</div>
<div align="justify">
This post will explain some termstore\tagging concept before explaining how to make these tags clickable through a relatively small development. I’ll also talk very briefly about how to put in place a custom tag page as a target of these clickable tags. </div>
<h4>
Not all tags are born equal</h4>
<div align="justify">
The Managed Metadata Service Application aka as the termstore or to put it simply: Tags serves a lot of purpose from document classification to libraries navigation, search facet (even navigation and friendly URL in SharePoint 2013).</div>
<div align="justify">
But it’s not so simple; Microsoft actually introduced two kind of tagging in SharePoint 2010:</div>
<ul>
<li> <div align="justify">
<img align="right" alt="image" border="0" height="39" src="http://lh3.ggpht.com/-B9gTh2keMJU/UR51mbYbchI/AAAAAAAAS3w/tt-ib2XZVhg/image%25255B7%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; float: right; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="286" />Tags as properties of documents (actual tags thereafter) where the property values are picked from a list of possible values (part of the termstore with <b>Managed Metadata typed column</b> or whole termstore with <b>Enterprise Keyword site column</b>). Users can be allowed to submit values (folksonomy basis). The tag becomes a property of the document and actually describes it. The tag value is cached in the site collection itself in an hidden library (always at <a href="http://yoursite/Lists/TaxonomyHiddenList">http://<strong><em>YOURSITE</em></strong>/Lists/TaxonomyHiddenList</a>)</div>
</li>
<li> <div align="justify">
<img align="right" alt="image" border="0" height="65" src="http://lh3.ggpht.com/-NzYJIE5Kpu0/UR51nEqQLMI/AAAAAAAAS34/h6JMav8-BVk/image%25255B8%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; float: right; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="113" />Tags as social actions (Social Tags), users can also in some places (at least enabled Document Libraries, Pages) social tags items. The tags values are picked from the termstore, however in this case the tags is not actually associated with the documents, it’s actually a property of the user. This action is not written down in the site collection content database at all but only lay in the User Profile Social database.</div>
</li>
</ul>
There is a major difference between these two types of tagging, one is an actual document property that can be used to classify and find the document, the other one is just a social action. <br />
<img alt="image" border="0" height="318" src="http://lh4.ggpht.com/-Ys5-8RHUKhI/UR51n6v-nOI/AAAAAAAAS4A/vYWUE9qblOw/image%25255B39%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="538" /><br />
<div align="justify">
Microsoft decided to make social tags clickable, these links points to the tagpage. However to make sure we get confused, the tagpage actually just display the contents that has been “social tagged”. If a document has been classified with an actual tag, it will not appear in the tagpage. This is because the tagpage is actually a page to display the social actions of the users, the fact that it lay in the user profile web application leaves no doubt.</div>
<div align="justify">
The issue is that social tags are not so useful for actual content management whereas actual tags are a must. Thus we realized we had no choice but to make these tags clickable and create our own tag page.</div>
<h4>
Click me ! Click me !</h4>
<div align="justify">
For the sake or maintainability\ease of use\compatibility and future evolutions we decided not to create a custom field type. Instead we focused our efforts on finding a way to make the out of the box field types clickable. There are actually only two of these, the SingleTaxonomyFieldType and MultipTaxoFieldType that are used for both Enterprise Keywords site columns and Managemed Metadata columns. We wanted to stick with supported customization so we made use of an extensibility option proposed with SharePoint 2010 (MSDN: <a href="http://msdn.microsoft.com/en-us/library/ff604024(v=office.14).aspx" target="_blank">Overview of XSLT List View Rendering System</a> http://msdn.microsoft.com/en-us/library/ff604024(v=office.14).aspx ) that allow to change the rendering of an existing type, a real improvement from SharePoint 2007 by the way.</div>
<div align="justify">
So to change multiple tags fields to red, create a xsl file named fldtypes_WHATYOUWANT.xsl in \Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\XSL</div>
<br />
<br />
<table border="0" cellpadding="2" cellspacing="0" style="width: 600px;"><tbody>
<tr> <td valign="top" width="598"><pre class="brush: xml"><xsl:stylesheet version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<br />
<xsl:template match="FieldRef[@FieldType='TaxonomyFieldTypeMulti']" <br /> priority="1" mode="Lookup_body">
<br />
<xsl:param name="thisNode" select="."/>
<br />
<span style="color:red">
<br />
<xsl:value-of select="$thisNode/@*[name()=current()/@Name]"/>
<br />
</span>
<br />
</xsl:template>
</xsl:stylesheet></pre>
<br /></td> </tr>
</tbody></table>
<br />
<br />
Beware of the priority setting above, that’s the key to make sure your customization is applied. You can quick-test that manually by placing the file and IISRESET.<br />
<br />
<br />
With a bit more work to get the actual link we need, here is the result<br />
<br />
<div align="center">
Before</div>
<img alt="image" border="0" height="48" src="http://lh4.ggpht.com/-6hxI_8lDJX4/UR51pDvJuSI/AAAAAAAAS4Q/mcAboubNKdk/image_thumb%25255B5%25255D.png?imgmax=800" style="background-image: none; border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /><br />
<br />
<div align="center">
<strong>After</strong></div>
<img alt="image" border="0" height="52" src="http://lh3.ggpht.com/-wntTBNxKaG4/UR51qvCOFaI/AAAAAAAAS4g/IXlvVyxyfs8/image_thumb%25255B3%25255D.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /><img alt="image" border="0" height="50" src="http://lh3.ggpht.com/-2f7kinbDBPQ/UR51r7T1sXI/AAAAAAAAS4w/xZIQYWDUbXM/image_thumb%25255B4%25255D.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /><br />
<br />
<br />
<div align="justify">
Cherry on the cake, there isn’t anything easier to deploy with a WSP, absolutely no code involved, just a folder mapping in Visual Studio.</div>
<br />
<br />
<div align="justify">
Note that this works fine for list\libraries views when displaying multiple items, when displaying a single item (View Form), we used a small JavaScript to introduce the link, displaying only a single item means that performance is not an issue in this case.</div>
<br />
<br />
<h4>
A link, but where to ?</h4>
<br />
<br />
<div align="justify">
<a href="http://en.wikipedia.org/wiki/Link_(The_Legend_of_Zelda)" target="_blank"><img align="left" border="0" height="90" src="http://fc00.deviantart.net/fs71/f/2012/220/5/3/original_link_sprite_by_eri_tchi-d4bv53t.png" style="background-image: none; border-width: 0px; display: inline; float: left; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="" width="76" /></a>It’s great to have a link but links are supposed to point somewhere. As the default tag page only uses social tags it’s useless so we decided to create our own tag page. </div>
<br />
<br />
<div align="justify">
The easiest solution we found to have both speed and security trimming was the search engine. Thus all the heavy-lifting is done by search while we can focus on displaying these results. This is possible because the search engine (tested on FAST 4 SharePoint, not Enterprise Search) has got a dedicated managed property to store tags that is queryable : Owsmetadatafacetinfo. This is the one used to render the tags facet on out of the box search pages.</div>
<br />
So to test it, just run a search for :<br />
<blockquote>
<br />
<br />
Owsmetadatafacetinfo:<em>ATAG</em><br />
<br /></blockquote>
<br />
<br />
That’s it plain and simple and now you have the main ingredient to build your own tag page from scratch.<br />
<br />
<h4>
Conclusion</h4>
It first seemed like a major challenge at first to make tags as document properties useful (clickable + tag page) in the end it’s actually fairly simple when you know the tricks and the results is definitely worth it. If you wonder about SharePoint 2013, this development has not yet been tested in this configuration, though we know for sure that it will be needed as tags are still not clickable in SharePoint 2013.The good news SP2013 news is that there seems to be an out of the box tag page that actually work since it’s based on search. I will test it more extensively and let you know.Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com0tag:blogger.com,1999:blog-28148811.post-17961275800144334732012-03-27T22:05:00.001+02:002012-03-27T22:05:01.766+02:00SharePoint 2010 Search – december CU warning<p align="justify">If you are currently running a pre December 2011 CU farm and have set up custom search center be careful before installing it. It seems like the maximum number of filters per refiner limits have been set to 250. We were previously using a value of 255 for a refiner. Thus installing the CU (<a href="http://support.microsoft.com/kb/2597058" target="_blank">SPF</a>, <a href="http://support.microsoft.com/kb/2597014" target="_blank">SPF</a>) broke our search center page with the following error:<u></u><u></u></p> <blockquote> <p>Internal server error exception: System.ArgumentException: Max number of filters has to be between 0 and 250     at Microsoft.Office.Server.Search.WebControls.FilterCategory.set_MaxNumberOfFilters(Int32 value)<u></u><u></u></p> </blockquote> <p><u></u><u></u></p> <p align="justify">After discovering the issue we changed to value to 0 (display all the filters according to MSDN <a href="http://msdn.microsoft.com/en-us/library/ff625183.aspx">http://msdn.microsoft.com/en-us/library/ff625183.aspx</a>, thank you Wesley for the suggestion by the way :) )<u></u><u></u></p> <blockquote> <p><WpNs0:UbiRefineMentWebPart FilterCategoriesDefinition<u></u><u></u></p> <p>    MaxNumberOfFilters=&quot;255&quot;<u></u><u></u></p> </blockquote> <p>to<u></u><u></u></p> <blockquote> <p><WpNs0:UbiRefineMentWebPart FilterCategoriesDefinition<u></u><u></u></p> <p>    MaxNumberOfFilters=&quot;0&quot;<u></u><u></u></p> </blockquote> <p><u></u><u></u></p> <p><u></u><u></u></p> <p>And problem solved.<u></u><u></u></p> <p><u></u><u></u></p> <p>More complete log below for searching purpose :<u></u><u></u></p> <p><em><font size="1">03/20/2012 16:16:07.85 w3wp.exe (0x1578)       0x1724  SharePoint Server Search           Query   dn1p                Medium              Filter category FASTMaxNumberOfFilters in the config is in wrong format.Input string was not in a correct format.<u></u><u></u></font></em></p> <p><em><font size="1">03/20/2012 16:16:07.85 w3wp.exe (0x1578)       0x1724  SharePoint Server Search           Query   g1j9                Exception           Internal server error exception: System.ArgumentException: Max number of filters has to be between 0 and 250     at Microsoft.Office.Server.Search.WebControls.FilterCategory.set_MaxNumberOfFilters(Int32 value)     at Microsoft.Office.Server.Search.WebControls.RefinementManager.ConfigureCategories()     at Microsoft.Office.Server.Search.WebControls.RefinementManager.Initialize(Location location)     at Microsoft.Office.Server.Search.WebControls.CoreResultsDatasourceView.CreateLocationList()     at Microsoft.Office.Server.Search.WebControls.CoreResultsDatasourceView.SetPropertiesOnQdra()     at Microsoft.Office.Server.Search.WebControls.SearchResultsBaseWebPart.EnsureWebpartReady() System.ArgumentException: Max number of filters has to be between 0 and 250     at Microsoft.Office.Server.Search.WebControls.FilterCategory.set_MaxNumberOfFilters(Int32 value)     at Microsoft.Office.Server.Search.WebControls.RefinementManager.ConfigureCategories()     at Microsoft.Office.Server.Search.WebControls.RefinementManager.Initialize(Location location)     at Microsoft.Office.Server.Search.WebControls.CoreResultsDatasourceView.CreateLocationList()     at Microsoft.Office.Server.Search.WebControls.CoreResultsDatasourceView.SetPropertiesOnQdra()     at Microsoft.Office.Server.Search.WebControls.SearchResultsBaseWebPart.EnsureWebpartReady()<u></u></font></em></p> Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com1tag:blogger.com,1999:blog-28148811.post-67523244685254345402011-07-23T16:53:00.001+02:002011-07-23T16:55:14.331+02:007 tips and tricks about the User Profile Replication Engine<p><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://lh5.ggpht.com/-ms1X2Ngw7ew/TirgTcaBPdI/AAAAAAAAHKA/lPlSUUA2BAM/image%25255B6%25255D.png?imgmax=800" width="159" height="181" /> </p> <p> </p> <p>The <a href="http://technet.microsoft.com/en-us/library/cc663011.aspx">SharePoint User Profile Replication Engine</a> (part of the SharePoint Administration Toolkit) is a powerful beast that you can use to:</p> <p> </p> <p> </p> <p> </p> <ul> <li>Migrate user profiles from a different farm to your farm (MOSS 2007 to SPS 2010 IS supported)</li> <li>Synchronize user profiles from a master a farm to a different farm (geographical replication or disaster recovery farm replication)</li> </ul> <p align="justify">I have been playing with this tool a bit lately and here are a few things I noticed that might interest you. First of I would advise you to start with the official documentation at: <a href="http://technet.microsoft.com/en-us/library/cc663011.aspx">http://technet.microsoft.com/en-us/library/cc663011.aspx</a> . You will most likely only use the full and incremental commands.</p> <h4>1 -Full replication DOES NOT use any windows service</h4> <p align="justify">The Full synchronization ( <a href="http://technet.microsoft.com/en-us/library/ff823730.aspx">Start-SPProfileServiceFullReplication</a> )does not uses the Windows Service (aptly named “Replication Engine”) used by the incremental command (<a href="http://technet.microsoft.com/en-us/library/ff823733.aspx">Start-SPProfileServiceIncrementalReplication</a>). This is important as it means that the full sync is done with the account you launched the command line with WHEREAS the incremental sync is done with the “Replication Engine” service account. Knowing which account is running is important to know which account needs the permissions on the User Profile Service Applications. </p> <h4>2 - Local Admin permissions IS NOT needed for incremental sync</h4> <p>Running the incremental sync (i.e. the windows service) is possible with a non-local administrator account, but it needs: </p> <ul> <li>Full permissions on the local folder where the replication engine is installed (C:\Program Files\Microsoft\SharePoint 2010 Administration Toolkit\Replication Engine)</li> <li>Full permissions on the registry hive </li> <ul> <li>HKLM:\Software\Microsoft\Replication Engine</li> <li>HKLM:\SYSTEM\CurrentControlSet\services\eventlog</li> <li>HKLM:\Software\Microsoft\EnterpriseCertificates</li> </ul> </ul> <p align="justify">This is not based on any official documentation; I had to use Process Explorer to actually see what was preventing the Replication Engine from starting when running with a non-local admin account. The last two permissions might be optional but I added these anyway to be on the safe side. So far I haven’t seen any downside to this workaround.</p> <h4>3 - Full replication IS NOT needed before starting incremental sync</h4> <p align="justify">At least it is not always needed. If the User Profiles are already in sync because you did a fresh install and imported the profiles on source and destination with no other changes, you might skip the full sync and start with the incremental sync. </p> <p align="justify">But if there is any difference between your two User Profiles SAs, start with the full as these differences will not be propagated. </p> <p align="justify">In fact the incremental sync only propagates information that has been changed while it is running. </p> <h4>4 - Account changing option (credential parameter) behaves badly</h4> <p align="justify">The credential parameter of the Start-SPProfileServiceIncrementalReplication should be used to specify the windows service credential on the first run according to the <a href="http://technet.microsoft.com/en-us/library/ff823733.aspx">documentation</a>, well I don’t because it works erratically giving inconsistent results. Instead I set the windows service account itself. You can even do it in scripts.</p> <h4>5 - Social sync IS supported BUT</h4> <p align="justify">Social sync doesn’t included managed metadata (because it isn’t part of the User Profiles Service Application obviously) event though tagging is based on managed metadata. In fact tagging is stored in the User Profile DB as reference to the managed metadata entry. </p> <p align="justify">Thus if you need to replicate tags you MUST replicate the managed metadata SA data as well.</p> <h4>6 - MySite URL CAN be replaced with the central administration Url </h4> <p align="justify">The documentation tells you to use the MySite Host Url for Source and destination but you can use the central administration URL as well.</p> <p align="justify">In DRP (Disaster Recovery Plan) configuration it might be cumbersome to do so as URLs are shared on the source and destination farm. But the central administration URL being based on machine names is different on both farms.</p> <p align="justify">Beware: this might depend on whether or not you User Profile SA is in the default Service Application Proxy group. </p> <h4>7 - Incremental sync is as fast as light</h4> <p>Yup it is seriously fast, so fast I thought my test protocol was broken when I started to test the replication :)</p> Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com12tag:blogger.com,1999:blog-28148811.post-19084599835286707292011-06-30T12:32:00.004+02:002011-07-01T13:45:38.754+02:00Beware of SharePoint 2010 Web Analytics on SQL Server Enterprise<p><a href="http://jonathanroussel.com/repo/blogpro/Beware-of-SharePoint-2010-Web-Analytics-_AF54/image.png"><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="image" border="0" alt="image" align="left" src="http://jonathanroussel.com/repo/blogpro/Beware-of-SharePoint-2010-Web-Analytics-_AF54/image_thumb.png" width="168" height="163" /></a>You might have missed this information (we did :( ) but when running your SharePoint 2010 farm on SQL Server 2008 Enterprise (or 2008 R2), the Web Analytics reporting database uses the table partitioning feature provided in SQL Server. </p><p> </p><p> </p><p> </p><blockquote><p>For large-scale environments, we recommend that you run the Web Analytics service application Reporting database on a server that is running SQL Server 2008 Enterprise Edition so that the Web Analytics service application can take advantage of table partitioning.</p><p>            </p><p>         From: <a href="http://technet.microsoft.com/en-us/library/cc678868.aspx">Databases Types and Descriptions</a> (<a href="http://technet.microsoft.com/en-us/library/cc678868.aspx">http://technet.microsoft.com/en-us/library/cc678868.aspx</a>)</p></blockquote><p>What this means is that your reporting databases will span one additional “NDF” file (and file group, named with the Aggregation DATE suffix) every week as illustrated below:</p><p><a href="http://jonathanroussel.com/repo/blogpro/Beware-of-SharePoint-2010-Web-Analytics-_AF54/clip_image001.jpg"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image001" border="0" alt="clip_image001" src="http://jonathanroussel.com/repo/blogpro/Beware-of-SharePoint-2010-Web-Analytics-_AF54/clip_image001_thumb.jpg" width="466" height="82" /></a></p><p>We realized this while trying to setup the logshipping of this base (which is supported according to this page by the way).</p><p>Hope it helps !</p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com11tag:blogger.com,1999:blog-28148811.post-11168211287759049182011-02-06T17:53:00.003+01:002011-02-06T17:54:55.533+01:00SharePoint 2010 – Resizing the Ribbon bar<p align="justify"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://lh5.ggpht.com/_UjyR4_TTJjc/TU7SCcHB9vI/AAAAAAAAHGY/Nz0KgeqPVoI/image_thumb%5B1%5D.png?imgmax=800" width="244" height="123" /> Recently I was asked to add some element in the ribbon upper part just before the Site Actions Menu. Thus I needed to increase the height of the upper part of the ribbon to fit our content (blue part in the screenshot above). </p><br />
<br />
<h4>Problem</h4><p align="justify">After spending an insane amount of time on what seemed so simple, I managed to get it kinda working. I say “kinda” because no matter what I did I couldn’t get the ribbon to display correctly when it was opened.</p><p align="justify">After checking this article from the SharePoint team: <a href="http://sharepoint.microsoft.com/blog/Pages/BlogPost.aspx?PageType=4&ListId=%7b72C1C85B-1D2D-4A4A-90DE-CA74A7808184%7d&pID=426" target="_blank">http://sharepoint.microsoft.com/blog/Pages/BlogPost.aspx?PageType=4&ListId={72C1C85B-1D2D-4A4A-90DE-CA74A7808184}&pID=426</a></p><p align="justify">I understood that it came from a FixRibbonAndWorkspaceDimensions() javascript function from init.js that just kept setting the height at 44px (ribbon collapsed) or 135px (ribbon opened) no matter what my CSS said. The culprit line is:</p><blockquote><p>var baseRibbonHeight=RibbonIsMinimized() ? 44 : 135;</p></blockquote><p align="justify">No need to tell you that after hearing Microsoft boast about their compliance with the latest Web Design best practices, I was expecting more than to find hard-coded height values in a JavaScript file…</p><h4>Solution</h4><p align="justify">Yet everything isn’t lost as the actual ribbonHeight is the aforementioned value plus a padding value </p><blockquote><p>var ribbonHeight=baseRibbonHeight+g_wpadderHeight;</p></blockquote><p align="justify">Thus if you want <strong>to increase the ribbon height, you just need to set the javascript variable g_wpadderHeight to the value you want to increment</strong>. You might do that in your masterpage as such :</p><blockquote><p><script type="text/javascript"></p><p>g_wpadderHeight = 30;</p><p></script></p></blockquote><p align="justify">Something else to note, the WebPart adding part of the ribbon stopped displaying the “Add”, “Cancel” button after resizing the ribbon bar as they were out of the box. I solved this problem with a bit of css :</p><blockquote><p>.ms-wpadder-buttonArea{</p><p>padding-bottom:30px;</p><p>}</p></blockquote>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com11tag:blogger.com,1999:blog-28148811.post-32000884986179572802011-01-20T21:18:00.006+01:002011-02-06T17:56:07.800+01:00Custom site logo not appearing on WebPart page<p><img style="margin: 0px 10px; display: inline" align="left" src="http://www.wssdemo.com/_layouts/images/siteIcon.png" />As you probably all know, SharePoint 2010 allows site administrators to change the sites logos just like 2007 did. This is done on the “Title, description, and icon” page</p><p><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://lh5.ggpht.com/_UjyR4_TTJjc/TTiYhtfaf1I/AAAAAAAAHFs/zg2-auKaJP8/clip_image002_thumb%5B1%5D.jpg?imgmax=800" width="244" height="61" /></p><p><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="clip_image004" border="0" alt="clip_image004" align="right" src="http://lh6.ggpht.com/_UjyR4_TTJjc/TTiYipX3lDI/AAAAAAAAHF0/8j3grzGpISw/clip_image004_thumb%5B2%5D.jpg?imgmax=800" width="244" height="148" /></p><p>The picture then appears in the top left of the site pages, just before the page title/breadcrumb</p><p> </p><p><br />
<br />
<br />
<br />
<img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="clip_image006" border="0" alt="clip_image006" align="right" src="http://lh3.ggpht.com/_UjyR4_TTJjc/TTiYjmXYvGI/AAAAAAAAHF8/iDBqZagoJbE/clip_image006_thumb%5B1%5D.jpg?imgmax=800" width="179" height="103" /><br />
<br />
The trouble is that this doesn’t work on WebPart pages, no matter what you do; users will still see the default yellow icon.</p><p> </p><h4>Cause</h4><p><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="clip_image008" border="0" alt="clip_image008" align="right" src="http://lh3.ggpht.com/_UjyR4_TTJjc/TTiYkRJFIRI/AAAAAAAAHGE/nUCO8Fe_OBU/clip_image008_thumb%5B2%5D.jpg?imgmax=800" width="132" height="80" /></p><p>WebPart pages use the TitleBarWebPart, this WebPart allows you to specify a title and logo for the page using the button in the ribbon bar</p><p>The problem here is that whatever you do, this Web Part always overrides your site logo setting. If you specify a page specific logo along with the title, it will use it. If you don’t specify a page specific logo, it will use the default SharePoint logo.</p><p>This overriding is done in javascript by the code below that you will find at the end of your web part page :</p><blockquote><pre>var logoImg = documentGetElementsByName('onetidHeadbnnr0');
if (logoImg != undefined && logoImg[0] != undefined)
logoImg[0].src='/_layouts/images/siteIcon.png';</pre><br />
</blockquote><br />
This javascript code is generated by the TitleBarWebPart, the “/_layouts/images/siteIcon.png” is replaced with the page specific logo if you set one. Thus this WebPart systematically overrides the site wide logo settings.<br />
By the way you will notice that it doesn’t work under Chrome 8 because of a Javascript error.<br />
<h4>Solution</h4><br />
Aaron Han suggested removing the Web part from the pages impacted on a MSDN forum:<br />
<a name="OLE_LINK1"></a><a target="_blank" href="http://social.msdn.microsoft.com/Forums/en-US/sharepoint2010customization/thread/9706669e-0488-45cd-9cf6-2edfef91f77f">http://social.msdn.microsoft.com/Forums/en-US/sharepoint2010customization/thread/9706669e-0488-45cd-9cf6-2edfef91f77f</a><br />
If you don’t want to edit every single WebPart page and/or if you want to retain the ability to change the page title I have another solution for you.<br />
My solution is to change the SiteLogoImage node name in the master page. Thus the javascript generated by the PageTitleWebPart is no longer able to change the logo.<br />
<br />
<h4>Details</h4>Open your master page and find the line starting with:<br />
<blockquote><SharePoint:SiteLogoImage name="onetidHeadbnnr0"<br />
</blockquote>And replace the “onetidHeadbnnr0” name with something else; “onetidHeadbnnr1” will do the trick.<br />
<h4>Conclusion</h4>I haven’t seen any drawback with this technique, yet :). Tell me if you do !Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com10tag:blogger.com,1999:blog-28148811.post-15610660329784408422010-08-29T20:06:00.001+02:002011-02-06T17:56:20.704+01:00Percentile in PowerPivot DAX<table border="0" cellspacing="0" cellpadding="2" width="100%"><tbody>
<tr> <td valign="top" width="262"><a href="http://en.wikipedia.org/wiki/File:Standard_deviation_diagram.svg"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://jonathanroussel.com/repo/blogpro/PercentileinPowerPivotDAX_10733/image.png" width="316" height="166" /></a></td> <td valign="top" rowspan="2"> <p>When analyzing data, I often find myself computing the percentile value. As I am a big fan of <a href="http://www.powerpivot.com/">PowerPivot</a>, I went with it lately to analyze some data and tried to get the 90<sup>th</sup> percentile of my series. So I chose to create a DAX measure and went looking for the PERCENTILE function only to discover that:</p></td> </tr>
<tr> <td valign="top" width="262"> <p> <font size="1">Normal Distribution courtesy of </font><a href="http://en.wikipedia.org/wiki/File:Standard_deviation_diagram.svg"><font size="1">Peter Strandmark @ Wikipedia</font></a></p><p></p></td> </tr>
</tbody></table><blockquote><p><strong>PowerPivot DAX doesn't support PERCENTILE! Even more shocking, neither is the much more common MEDIAN measure supported.</strong></p></blockquote><p>Don't panic folks; <a href="http://sqlblog.com/blogs/marco_russo/archive/2010/07/20/median-calculation-in-dax.aspx">Marco Russo</a> was kind enough to share his way of computing the median. With a tiny tweak it allows us to compute the 90<sup>th</sup> percentile as such: <table border="1" cellspacing="0" cellpadding="0"><tbody>
<tr> <td valign="top" width="614"> <pre>MINX(FILTER(VALUES(MyDataSerie1[Col1]),
CALCULATE(COUNTROWS(MyDataSerie1),
MyDataSerie1[Col1] <= EARLIER(MyDataSerie1[Col1]) )
> COUNTROWS(MyDataSerie1)*<strong>0.9</strong>),
MyDataSerie1[Col1])</pre></td> </tr>
</tbody></table></p><p>The important part is 0.9. Just replace it with 0.5 for the median, 0.25 for the first quartile and so forth.</p><p>I bet the Excel and SQL folks had good reasons not to include these functions, if you have any idea why, leaves me a message. I also posted a line on the MSDN forum(<a href="http://social.msdn.microsoft.com/Forums/en/sqlkjpowerpivotforexcel/thread/b1ccf0e6-d5d3-4405-9748-4381a310b57b">http://social.msdn.microsoft.com/Forums/en/sqlkjpowerpivotforexcel/thread/b1ccf0e6-d5d3-4405-9748-4381a310b57b</a> ).</p><h4>Accuracy of this measure</h4><p>I am no statistician, the formula looked ok but I wanted more assurance about its accuracy. Thus I fixed a little test to compare the percentile computed with this DAX measure to regular Excel PERCENTILE.INC and PERCENTILE.EXC formula. I computed the 5,25,50,75,90,95 percentiles using these 3 means for 3 different kind of number series and then averaged the difference between those :</p><table border="0" cellspacing="0" cellpadding="2" width="100%"><tbody>
<tr> <td valign="top">DiffINC is the difference in percentage between PERCENTILE.INC and the DAX measure. Same for DiffEXC.</td> <td valign="top"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://jonathanroussel.com/repo/blogpro/PercentileinPowerPivotDAX_10733/image1.png" width="360" height="169" /></td> </tr>
</tbody></table><p>As you can see, this DAX measure is giving results pretty close (less than 0,05% error) to the PERCENTILE.INC Excel formula. This is close enough for my needs anyway. Yet be careful, with smaller number series (less than 50 items), the error went up to reach values as high as 5% on some cases.</p><h4>Percentile Explanation</h4><p>By the way, for those unfamiliar with percentile, the Nth percentile is the value below which N% of the value fall. More details on <a href="http://en.wikipedia.org/wiki/Percentile">Wikipedia</a>.</p><p><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="clip_image004" border="0" alt="clip_image004" align="right" src="http://jonathanroussel.com/repo/blogpro/PercentileinPowerPivotDAX_10733/clip_image004.png" width="300" height="207" />Ok, so why it is useful you might ask, well it is common to analyze your data series without the extreme values that might indicate problem with your data source. An example is in the software performance testing field where you will usually consider the 90<sup>th</sup> or 95<sup>th</sup> values of the response time in order to know what the reasonable highest response time is without considering test aberrations or errors.</p><p><strong>N.B</strong>: Some of you might have noticed the new addition to the title of this blog: <strong>Jonathan's IT blog – SharingPointers</strong>, tell me what you think in the comments !</p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com4tag:blogger.com,1999:blog-28148811.post-75593510490675718532010-05-05T22:45:00.006+02:002010-05-05T22:57:57.945+02:00Using tabs in SharePoint 2010 central administration, a solution<p align="justify"><a href="http://sharepoint2010.microsoft.com/Pages/default.aspx" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://jonathanroussel.com/repo/blogpro/UsingtabsinSharePoint2010centraladminist_13B6B/image.png" width="238" height="71" /></a> I don’t know about you but tabbed navigation has become a must have for me in the past years. I mean who wants to open a different window for each and every web page.</p> <p align="justify">Well my friends, it seems like Microsoft remembers too fondly those pre-tab browsing days and wants us to return to this prehistoric era. I am talking about the infamous Javascript links one can find in the SharePoint 2010 Central Administration – <a href="http://technet.microsoft.com/en-us/library/ee721050%28office.14%29.aspx">User Profile Service Application</a> management page:</p> <p><a class="FancyMe" href="http://jonathanroussel.com/repo/blogpro/UsingtabsinSharePoint2010centraladminist_13B6B/image_3.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://jonathanroussel.com/repo/blogpro/UsingtabsinSharePoint2010centraladminist_13B6B/image_thumb.png" width="596" height="279" /></a> </p> <p>If you mouse over those links, you will see in the status bar that they are not actual links but instead Javascript calls:</p> <p><a class="FancyMe" href="http://jonathanroussel.com/repo/blogpro/UsingtabsinSharePoint2010centraladminist_13B6B/image_4.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://jonathanroussel.com/repo/blogpro/UsingtabsinSharePoint2010centraladminist_13B6B/image_thumb_3.png" width="244" height="122" /></a> </p> <p align="justify">If you add to that, the fact that the navigation is completely useless in this site, you have the recipe for a disastrous user experience as you can’t even open tab to compensate.</p> <p align="justify">Having to work with the User Profile Service Application for a client I got fed up with the situation and decided to act. As javascript is the swiss knife of SharePointer, I wrote a script to replace those javascripts link with actual links so that I can open these links in tabs if needed :</p> <p><a class="FancyMe" href="http://jonathanroussel.com/repo/blogpro/UsingtabsinSharePoint2010centraladminist_13B6B/image_5.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://jonathanroussel.com/repo/blogpro/UsingtabsinSharePoint2010centraladminist_13B6B/image_thumb_4.png" width="244" height="119" /></a> </p> <p align="justify">Voila, here are your tab-compliant links.</p> <p align="justify">As <a href="http://technet.microsoft.com/en-us/library/cc263526(office.14).aspx">FireFox is now fully supported by SharePoint</a>, I use this code in a <a href="https://addons.mozilla.org/en-US/firefox/addon/748">GreaseMonkey</a> user script. This way the script is applied on this page whatever the farm I am administering. Without even having to modify anything on the farms.</p> <p align="justify">To add the user script, nothing too fancy, just add “<strong>*/_layouts/ManageUserProfileServiceApplication.aspx*</strong>” in the include. And add the following as the code :</p> <pre class="brush: csharp">// Jonathan Roussel - http://blog.jonathanroussel.com
<br />// Make sure to Include */_layouts/ManageUserProfileServiceApplication.aspx*
<br />
<br />var cUrl=document.location.href;
<br />var aId = cUrl.substring(cUrl.indexOf("ApplicationID"));
<br />var links,link;
<br />
<br />links=document.getElementsByTagName("a");
<br />for(var i=0;i<links.length;i++)
<br />{
<br /> var link = links[i];
<br /> if(link.href.indexOf("javascript:AppendApplicationIdAndNavigate(")>=0)
<br /> {
<br /> link.href = link.href.substring(45,link.href.length-2) +aId;
<br /> }
<br />};</pre>
<br /><p>If you want a more portable solution, I also put this code together as a <a href="http://en.wikipedia.org/wiki/Bookmarklet">Bookmarklet</a>. Just drag and drop this link to your favorite bar. Thus whenever you are on the “Manage User Profile” page, just hit the link in the favorite bar to transform these nasty Javascript links into actual links.</p>
<br /><p><a href="javascript:{var cUrl=document.location.href;var aId = cUrl.substring(cUrl.indexOf('ApplicationID'));var links; var link;links=document.getElementsByTagName('a');for(var i=0;i<links.length;i++){var link = links[i];if(link.href.indexOf('javascript:AppendApplicationIdAndNavigate(')>=0){link.href = link.href.substring(45,link.href.length-2) +aId;}};}void(0);">SP2010_SCA_TabAllower</a></p>
<br /><p>Tested with IE8, FireFox 3.6, Chrome 4.1.</p> Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com1tag:blogger.com,1999:blog-28148811.post-31879262017553170802010-04-21T21:53:00.020+02:002010-04-22T14:36:01.356+02:00Awesomizing your SharePoint picture libraries in no time<p>Still using those plain olds SharePoint picture libraries? You know the libraries where a click on a thumbnail brings ups the DispaForm.aspx pages with details about the pics that none of your users care about. What about having your picture in your libraries shown this way instead :</p> <p><a class="FancyMe" href="http://jonathanroussel.com/repo/blogpro/FancyBox/Fancybox_ex1.png"><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="A much better look for SharePoint picture libraries" alt="A much better look, don't you think?" src="http://lh4.ggpht.com/_UjyR4_TTJjc/S89XoWwDN9I/AAAAAAAAGrk/bEjAZ0nw9Bk/image_thumb9.png?imgmax=800" border="0" height="229" width="407" /></a> </p> <p>Guess what, it’s as easy as ABC to enhance the way your picture libraries look like with very nice inpage popup.</p> <h4>The basics</h4> <p>To do that you need:</p> <ul> <li><strong><a href="http://jquery.com/" target="_blank">jQuery</a></strong>, a javascript library to ease development </li> <li><strong><a href="http://fancybox.net/" target="_blank">FancyBox</a></strong>, a jQuery plugin to handle picture zoom/magnification automatically </li> <li>A <strong>Content Editor Web Part</strong>, I use this editor web part to push my <strong>JavaScript</strong> code that will <ul> <ul> <li>Change the thumbnail so that they link to the full size picture instead of the Picture detail </li> <li>Tell fancybox to do its magic so that these regular links launches a zoom on the full size picture </li> </ul> </ul> </li> </ul> <h4>A detailed walkthrough</h4> <ul> <li><em>Get jQuery</em> from (<a href="http://jquery.com/">http://jquery.com/</a> ) </li> <li><em>Get FancyBox</em> from: (<a href="http://fancybox.net/">http://fancybox.net/</a> ) </li> <li><em>Extract the fancybox</em> folder from the zip you got </li> <li><em>Put the jQuery file and fancybox</em> in someplace your user can access. For the sake of simplicity I am going to put these files in a document library for this walkthrough. In a real world scenario I am putting these files in the 12 using a WSP. <ul> <ul> <ul> <ul> <ul> <li><em>Create</em> or open an existing <em>document library</em> </li> <li><em>Create a JS folder</em> (or not, I just like my stuff to be organized) </li> <li><em>Push the jquery-1.4.2.min.js and fancybox</em> folder in. </li> </ul> </ul> </ul> </ul> </ul> </li> </ul> <p><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://lh3.ggpht.com/_UjyR4_TTJjc/S89XpOFnPBI/AAAAAAAAGro/sbbPsmxKcUY/image15.png?imgmax=800" border="0" height="121" width="244" /> </p> <ul> <li>Now you can go to your Picture Library and Edit the page (screen grabbed from a French WSS Install) </li> </ul> <p><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="clip_image001" alt="clip_image001" src="http://lh5.ggpht.com/_UjyR4_TTJjc/S89Xq0sStxI/AAAAAAAAGrw/chRbbZ2Kbcg/clip_image001_thumb1.png?imgmax=800" border="0" height="167" width="244" /></p> <ul> <li>Add a Content Editor Web Part and edit it </li> <li>Open the “Source Editor” </li> </ul> <p><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="clip_image002" alt="clip_image002" src="http://lh6.ggpht.com/_UjyR4_TTJjc/S89XsF86GVI/AAAAAAAAGr4/yDHDMYakyhE/clip_image002_thumb1.png?imgmax=800" border="0" height="219" width="244" /></p> <p>Paste the following code</p> <pre class="brush: csharp"><script type="text/javascript" src="/Documents/JS/jquery-1.4.2.min.js"></script><br /><script type="text/javascript" src="/Documents/JS/fancybox/jquery.fancybox-1.3.1.pack.js"></script><br /><link rel="stylesheet" href="/Documents/JS/fancybox/jquery.fancybox-1.3.1.css" type="text/css" media="screen" /><br /><script type="text/javascript"><br />// Jonathan Roussel<br />$(document).ready(function() {<br />//for each IMG node children of a A node in a .thumbnail class section<br />$(".thumbnail a > IMG").each(function(){<br />if($(this).attr('alt') == 'Image')<br />{<br />// Replace thumbnail link from item page to the pic itself<br />var imageUrl = $(this).attr('src');<br />// Change http://moss/pics/_t/MyPics_jpg.jpg<br />// In - http://moss/pics/MyPics.jpg<br />// using a regular expression<br />imageUrl = imageUrl.replace(/((.)+)\/_t\/((.)+)_([a-z]{3})\.[a-z]{3}/gi,'$1/$3.$5');<br />$(this).parent().attr('href',imageUrl );<br />$(this).parent().attr('rel','Gallerie' );<br />$(this).attr('alt','');<br />//plugin fancybox<br />$(this).parent().fancybox({'cyclic':true});<br />}<br />});<br />});<br /></script></pre><ul><li>Press Ok and enjoy the magic of Fancybox. </li></ul>The result might not yet be perfect; the two following notes shall set everything straight.<br /><h4>Notes 1,of missing GUI pics</h4>The path to the pictures in the CSS might need to be modified for the pictures used by fancybox to work .<br />So if you don’t see any Loading, Close, Prev, Next button, open the CSS in the document library (/documents/js/fancybox/jquery.fancybox-1.3.1.css)<br />And replace<br /><pre class="brush: jscript">(src='/fancybox </pre>with<br /><pre class="brush: jscript">(src='/documents/js/fancybox</pre><br />Reload the Image Library in Internet Explorer and the pics shall be there.<br /><h4>Note 2, of using this with IE8:</h4><a class="FancyMe" href="http://jonathanroussel.com/repo/blogpro/FancyBox/Fancybox_ex2.png"><img style="border-width: 0px; display: inline; margin-left: 0px; margin-right: 0px;" title="Fancybox, SharePoint and IE8. Needs some fixing" alt="Fancybox, SharePoint and IE8. Needs some fixing" src="http://lh5.ggpht.com/_UjyR4_TTJjc/S89XtVUsxXI/AAAAAAAAGsA/hyjX_Iiz14M/clip_image004_thumb2.jpg?imgmax=800" align="right" border="0" height="244" width="197" /></a><br /><p>This component seems to have trouble with IE8 and SharePoint. Without a strict XHTML doctype the picture frame are messed up as you can see on the right:</p><br /><p> </p><p> </p><p><a class="FancyMe" href="http://jonathanroussel.com/repo/blogpro/FancyBox/Fancybox_ex3.png"><img style="border-width: 0px; display: inline; margin-left: 0px; margin-right: 0px;" title="Fancybox, SharePoint and IE8. A match fixed !" alt="Fancybox, SharePoint and IE8. A match fixed !" src="http://lh3.ggpht.com/_UjyR4_TTJjc/S89XvFoHtYI/AAAAAAAAGsM/TTX1lGnUqAg/clip_image006_thumb4.jpg?imgmax=800" align="left" border="0" height="244" width="205" /></a></p><p>As adding an XHTML strict doctype was a no go, I tried to circumvent the problem by removing the frame and setting the white frame right. Here is the result:</p><br /><p> </p><p>Not as nice as what fancybox can do (lost the gradient border) but good enough for my purpose. To get this result you will need to do these modifications in the css file (the same on you modified in note 1):</p><br /><table border="0" cellpadding="0" cellspacing="0" width="550px"><tbody><tr><br /><td valign="top" width="50%"><br /> <p align="center"><strong><span style="color: rgb(34, 62, 255);">Original & Instructions</span></strong></p><br /></td><td valign="top" width="50%"><br /> <p align="center"><strong><span style="color: rgb(34, 62, 255);">Target</span></strong></p><br /></td></tr><tr><td valign="top"><br /> <strong>#fancybox-outer replace line</strong><br /> <p>background: #FFF;</p><br /></td> <td valign="top"><br /> <p>top:-10px !important;<br />left:-10px !important;<br />/*background: #FFF; */</p><br /></td></tr><tr> <td valign="top"><br /> <strong>#fancybox-inner replace line</strong><br /> <p>top: 0;<br />left: 0;</p><br /></td><td valign="top"><br /> <p>top: 0 !important;<br />left: 0 !important;<br /></p><br /></td></tr><tr><td valign="top"><br /> <p><strong>.fancy-bg add line</strong> </p><br /></td> <td valign="top"><br /> <p>display: none !important;</p><br /></td></tr><tr><td valign="top"><br /> <p><strong>Add at the end of the file</strong></p><br /></td><td valign="top"><br /> <pre>.fancybox-ie {<br />background-color:#fff;<br />}</pre></td></tr></tbody></table><br /><p></p>After saving the CSS and reloading the page you should be all set and ready to receive your end user congratulations :)<br /><blockquote><p><span style="font-size:130%;">Of course, this is only a start. The next step would be to have the picture retrieved by a Content Query Web Part with the fancybox magic added. It would mean losing the option to download multiple picture and it would allow for an even better rendering.</span></p></blockquote>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com24tag:blogger.com,1999:blog-28148811.post-59855491198822804092010-03-28T19:47:00.003+02:002010-03-28T19:52:54.764+02:00PowerPivot - Choosing a calculated column type<p><a title="Official PowerPivot for Excel logo by Microsoft" href="http://www.powerpivot.com/"><img style="border-width: 0px; display: inline; margin-left: 0px; margin-right: 0px;" title="clip_image001" alt="clip_image001" src="http://lh5.ggpht.com/_UjyR4_TTJjc/S6-WKUKkwbI/AAAAAAAAGoY/dKzv4HFqQe4/clip_image001%5B8%5D.png?imgmax=800" width="119" align="left" border="0" height="120" /></a>Lately I have been using PowerPivot (more details on this at the end of this post) and I came across a problem whose solution might interest others. </p> <p> </p><p><br /></p><p><br /></p><p><br /></p> <h4>The Problem</h4> <p>As I created a calculated column based on a date column, the result was always displayed as a number instead of a date. Worst the drop down list where you can choose the type of the column was greyed out.</p> <p>Here is an example; CalculatedColumn1 is created using some number function (ROUNDDOWN). Yet I am working with Dates, while PowerPivot understandably consider the results to be a number, one can’t override this automatic setting of the Data Type. The “Data Type” DropDown list is just greyed out with a value of Number (Nombre in French in the screenshot below) :</p> <p><a href="http://lh4.ggpht.com/_UjyR4_TTJjc/S6-WLK1E9jI/AAAAAAAAGoc/lDY72hBbv5w/s1600-h/image%5B7%5D.png"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://lh3.ggpht.com/_UjyR4_TTJjc/S6-WMMQftQI/AAAAAAAAGog/SJizWiJd2jA/image_thumb%5B3%5D.png?imgmax=800" width="463" border="0" height="153" /></a> </p> <p>The obvious drawback is that my column isn’t very readable, I mean no normal human beings can understand that 40255 mean 18/03/2010 00:00, else leave me a comment, I would be interested to meet you :)</p> <h4>My solution</h4> <p>Here is my workaround, just throw a date function in your function. In my case I choose to add TIME(0,0,0) which is a neutral operation :</p> <p><img style="border-width: 0px; display: inline;" title="clip_image004" alt="clip_image004" src="http://lh3.ggpht.com/_UjyR4_TTJjc/S6-WMyhwnlI/AAAAAAAAGok/73-GQd72nuU/clip_image004%5B11%5D.png?imgmax=800" width="462" border="0" height="44" /></p> <p>Thus PowerPivot will understand that your column is a date, and you will be able to select a Date format:</p> <p><a href="http://lh3.ggpht.com/_UjyR4_TTJjc/S6-WNXBqr8I/AAAAAAAAGoo/_yXB40mtsdI/s1600-h/image%5B3%5D.png"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://lh4.ggpht.com/_UjyR4_TTJjc/S6-WOcS75XI/AAAAAAAAGos/JcRvhyoggZM/image_thumb%5B1%5D.png?imgmax=800" width="457" border="0" height="169" /></a> </p> <h4>Some Information on PowerPivot (aka Gemini)</h4> <p>For those who don’t know what <a href="http://www.powerpivot.com/">PowerPivot</a> is, you might know by its codename, Gemini. It is a Microsoft Addin for Excel and SharePoint 2010 that allows you to analyze tons of data very easily. It’s supposedly really fast due to its in In Memory Analysis. For BI noobs (a group I am sadly part of) you might see it as a personal version of Anaysis Service (PowerPivot for Excel) or as a Team flavored BI (PowerPivot for SharePoint), on this subject I found this <a href="http://blogs.msdn.com/powerpivot/archive/2010/03/12/comparing-analysis-services-and-powerpivot.aspx">blog post</a> by the PowerPivot Team very interesting (<a href="http://blogs.msdn.com/powerpivot/archive/2010/03/12/comparing-analysis-services-and-powerpivot.aspx">http://blogs.msdn.com/powerpivot/archive/2010/03/12/comparing-analysis-services-and-powerpivot.aspx</a>).</p> <p>Microsoft released a series of nice videos to explain PowerPivot, here is the first one :</p> <p align="center"><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/gAxX3NHVlkc&hl=en_US&fs=1&"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/gAxX3NHVlkc&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="320" height="192"></embed></object></p> <p>Here is what PowerPivot promises and, as far as my experience went, delivers:</p> <ul> <li>Analysis (Pivot Table and graph) of Data from multiples sources (DataBase, Excel files, flat files) </li> <li>Analysis of huge volume Data (I am talking millions here) </li> <li>Integration of simple relational constraint between your data sources </li> <li>And maybe the coolest part is that this is available to any Information Worker already familiar with Excel. I would take this one with a grain of salt; your Information Worker needs to be quite technical savvy to fully benefit from this tool. </li> </ul> <p>Additionally the Integration with SharePoint is supposed to bring added performance and to deliver your reports more easily to multiple persons. I haven’t tested the integration, yet!</p> <p>After spending some quality time with PowerPivot I have got to admit being very enthusiastic about this product. I can see numerous scenarii where it would have saved me hours in the past (More details and cool links at the end of the post). I just can’t wait to set my hands on the RTM version of Excel 2010 and PowerPivot to enjoy this tool without worrying so much about the too frequent crashes (in my experience double clicking on a graph horizontal axis freezes quite often).</p> <p>To go further I would advise you to start with the official PowerPivot site (<a href="http://www.powerpivot.com/">http://www.powerpivot.com</a> ), especially the demo part.</p> <p>To my French reader I would also recommend the hilarious BI video by Têtes à Claques that you might have enjoyed at the 2010 Techdays in Paris :(<a href="http://www.microsoft.com/france/serveur/sql/secretedouard/">http://www.microsoft.com/france/serveur/sql/secretedouard/</a> )</p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com0tag:blogger.com,1999:blog-28148811.post-5502773395517021342010-03-06T11:59:00.003+01:002010-04-13T21:43:24.277+02:00Replacing delegate controls with custom actions<p align="justify"><a href="http://jquery.com/"><img style="border: 0px none; display: inline; margin-left: 0px; margin-right: 0px;" title="jQuery" alt="jQuery" src="http://lh4.ggpht.com/_UjyR4_TTJjc/S5I1j4Ty7BI/AAAAAAAAGk0/cLhLKqi6N_0/image%5B4%5D.png?imgmax=800" width="184" align="left" border="0" height="61" /></a> When using jQuery in a SharePoint application, you obviously need to deploy the jQuery javascript file. The deploy part is no big deal, the referencing is a bit more complex. In this post is the detail of a new way to reference the resources, it involves using Custom Action to load external resources such as javascript or css.</p> <h4>Current Solution</h4> <p align="justify">As explained by Jan Tielens (<a href="http://weblogs.asp.net/jan/archive/2008/11/20/sharepoint-2007-and-jquery-1.aspx">http://weblogs.asp.net/jan/archive/2008/11/20/sharepoint-2007-and-jquery-1.aspx</a> there are usually three solutions considered to be available to do that:</p> <ul> <li>Add a <script src> tag in a Content Editor Web Part </li> <li>Add a <script src> tag in the Master Page itself </li> <li>Add a <script src> tag dynamically in the <head> using a DelegateControl placed in the standard master pages </li> </ul> <p>In my case, only the third solution was usable. So I went with it, created my feature, added it to my solution.</p> <h4>The problem</h4> <p align="justify">The story would have ended here if it wasn’t for a detail I discovered quickly enough; the standard publishing pages (BlueGlassBand and so forth) do not have the AdditionalPageHead delegate control defined. Thus my solution worked really well with collaboration pages but failed on publishing pages.</p> <p align="justify">The obvious solution was to modify the master page used by my client to add the Delegate Control tag but the client didn’t want any modification to the master page. Thus I was at this point :</p> <blockquote> <p align="justify">How do I add a reference to some javascript and css files in the HTML <head> section of a page generated by a master page that doesn’t include any DelegateControl and that I can’t modify.</p> </blockquote> <h5>The solution</h5> <p align="justify">After digging a bit I found a very surprising (to me at least) but fully working solution. Use a Custom Action. </p> <p><a title="Nuts 2 on Flickr by Steffenz" href="http://www.flickr.com/photos/steffenz/2080578170/"><img style="border: 0px none; display: inline; margin-left: 0px; margin-right: 0px;" title="Nuts 2 on Flickr by Steffenz" alt="Nuts 2 on Flickr by Steffenz" src="http://lh4.ggpht.com/_UjyR4_TTJjc/S5I1kZukhiI/AAAAAAAAGk4/IWOqf5UcjSg/2080578170_3353a66e74_m%5B1%5D.jpg?imgmax=800" width="244" align="right" border="0" height="164" /></a> </p> <p>Before you start thinking I am nuts, let me explain, If you take a close look at the MSDN you will see that you can specify a ControlAssembly and a ControlClass, guess what, the class specified will do the actual rendering. Custom Actions aren’t just for Site Action Menu entries, ECB and so forth.</p> <p>So here is more detail:</p> <ul> <li>Create a class inheriting from CompositeControl </li> <li>Override the constructor so that I can plug a method in the Load event. </li> <li>In my method triggered on load, access the page header and add a LiteralControl to declare the scripts and css I need </li> </ul> <p>And here is a stripped down but fully working version of my code :</p> <!-- code formatted by http://manoli.net/csharpformat/ --> <table width="466" border="0" cellpadding="2" cellspacing="0"><tbody> <tr> <td valign="top" width="464"> <pre class="csharpcode"><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Collections.Generic;<br /><span class="kwrd">using</span> System.Text;<br /><span class="kwrd">using</span> System.Web.UI.WebControls;<br /><span class="kwrd">using</span> System.Web.UI.HtmlControls;<br /><span class="kwrd">using</span> System.Web.UI;<br /><br /><span class="kwrd">namespace</span> ItemsInTheSafeControl<br />{<br /> <span class="kwrd">class</span> SiteActionMenu : CompositeControl<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">const</span> <span class="kwrd">string</span> mStrIncludedRessources = <span class="str">"<script type=\"text/javascript\" src=\"/_layouts/jquery-1.3.2.min.js\">"</span>;<br /><br /> <span class="kwrd">public</span> SiteActionMenu()<br /> {<br /> <span class="kwrd">this</span>.Load += <span class="kwrd">new</span> EventHandler(SiteActionMenu_Load);<br /> }<br /> <span class="kwrd">protected</span> <span class="kwrd">void</span> SiteActionMenu_Load(<span class="kwrd">object</span> Sender, EventArgs E)<br /> {<br /> LiteralControl vLiteralControl = <span class="kwrd">new</span> LiteralControl(SiteActionMenu.mStrIncludedRessources);<br /> <span class="kwrd">this</span>.Page.Header.Controls.Add(vLiteralControl);<br /><br /> }<br /> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Render(HtmlTextWriter Writer)<br /> {<br /> }<br /> }<br />}</pre><br /> </td><br /> </tr></tbody></table>To plug this code as a custom action, I use the following ElementManifest<br /><table width="466" border="0" cellpadding="2" cellspacing="0"><tbody><tr><br /> <td valign="top" width="464"><!-- code formatted by http://manoli.net/csharpformat/ --><!-- code formatted by http://manoli.net/csharpformat/ --><br /> <pre class="csharpcode"><span class="kwrd"><?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span> ?<span class="kwrd">></span><br /><span class="kwrd"><</span><span class="html">Elements</span> <span class="attr">xmlns</span><span class="kwrd">="http://schemas.microsoft.com/sharepoint/"</span><span class="kwrd">></span><br /><span class="kwrd"><</span><span class="html">CustomAction</span><br /> <span class="attr">Id</span><span class="kwrd">="SAG_CR_Ressources_Deploy_Action"</span><br /> <span class="attr">Location</span><span class="kwrd">="Microsoft.SharePoint.StandardMenu"</span><br /> <span class="attr">GroupId</span><span class="kwrd">="SiteActions"</span><br /> <span class="attr">ControlAssembly</span><span class="kwrd">="SAG.CommentsRating, Version=1.0.0.0, Culture=neutral, PublicKeyToken=406cabeaa3d2932a"</span><br /> <span class="attr">ControlClass</span><span class="kwrd">="SAG.CommentsRating.WebParts.SiteActionMenu"</span><span class="kwrd">></span><br /><span class="kwrd"></</span><span class="html">CustomAction</span><span class="kwrd">></span><br /><span class="kwrd"></</span><span class="html">Elements</span><span class="kwrd">></span></pre></td><br /> </tr></tbody></table>Now you just package the ElementManifest in a feature, add your dll and create a solution out of it (wspbuilder is my tool of choice). Your solution manifest will need to specify a SafeControl tag to be added for your class/namespace in the web.config for your CompositeControl.<br /><p align="center"><strong>Here you go, a non-intrusive quite generic solution to plug additional resources into SharePoint.</strong></p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com0tag:blogger.com,1999:blog-28148811.post-75714965498738721662010-01-24T18:45:00.009+01:002010-02-23T18:23:18.029+01:00JSONP your ASP.Net Web Service – Direction to your destination<p><img style="border: 0px none ; display: inline; margin-left: 0px; margin-right: 0px;" title="The classical SOAP-WSDL Web Service stack" alt="The classical SOAP-WSDL Web Service stack" src="http://lh3.ggpht.com/_UjyR4_TTJjc/S1yHPqVkG4I/AAAAAAAAF8s/IGjHf_4_3Jk/image%5B44%5D.png?imgmax=800" width="121" align="left" border="0" height="113" /> I was recently developing a Comments & Rating SharePoint solution. As postbacks were forbidden (for good reasons, who loves postbacks ?), we used <a href="http://en.wikipedia.org/wiki/Jquery">jQuery</a> with a custom Web Service hosted in a SharePoint web application to try offering a nice experience to end-users.</p> <p>The custom WebService was to be invoked from pages located on foreign domains. As we had no control over those foreign sites (they weren’t even ASP.Net sites), we had to use <a href="http://en.wikipedia.org/wiki/JSONP#JSONP">JSONP</a> to make it works.</p> <p>While there is no major difficulty in JSONPing your ASP.net web services even if it is hosted in a SharePoint Web Application, I stumbled upon a couple of problem I wanted to share with you. So let me take you on the road to JSONP in your SharePoint solutions.</p> <h4>Freeway opened - a few turn on the road but no trouble ahead </h4> <p><img style="border: 0px none ; display: inline; margin-left: 0px; margin-right: 0px;" title="Free way opened - a few turn on the road but no trouble ahead" alt="Free way opened - a few turn on the road but no trouble ahead" src="http://lh4.ggpht.com/_UjyR4_TTJjc/S1yHQK8jZNI/AAAAAAAAF8w/PSMgUKu1rkw/image%5B47%5D.png?imgmax=800" width="173" align="right" border="0" height="119" /> I will not cover the basics of making your web service JSONP compliant, other bloggers have done a great job at that ( I would recommend <a href="http://bloggingabout.net/blogs/adelkhalil/archive/2009/08/14/cross-domain-jsonp-with-jquery-call-step-by-step-guide.aspx">Adel Khalil’s</a> and <a href="http://elegantcode.com/2008/12/02/calling-remote-aspnet-web-services-from-jquery/">Jason Grundy’s (check the comments)</a> posts among others). Neither will I talk about the basis of JSONP, just let me tell you it is an hack of the HTML script tag intended use that will let you call Web Services from other domains. Other ressources will let you understand why we need this hack <a href="http://snook.ca/archives/javascript/cross_domain_aj">(Jonathan Snook cross domain ajax : a quick summary</a>) and what this hack does (<a href="http://www.insideria.com/2009/03/what-in-the-heck-is-jsonp-and.html">Raymond Camden’s article does a great job at this</a>).</p> <p>There are really very few specifics to SharePoint as far as the Web Service is concerned. My SharePoint solution pushes the asmx file in a subfolder of the Layouts folder along with a web.config specific to this folder that contains the necessary configuration to support JSON (thus JSONP) in the Web Service. The Web Service code behind is deployed in the GAC.</p> <h4>Roadblock #1 – Does size matters ?</h4> <p><img style="border: 0px none ; display: inline; margin-left: 0px; margin-right: 0px;" title="Roadblock #1 " alt="Roadblock #1 " src="http://lh3.ggpht.com/_UjyR4_TTJjc/S1yHQlFUXgI/AAAAAAAAF80/rI3lo8_-hOE/image%5B46%5D.png?imgmax=800" width="132" align="right" border="0" height="122" /> Once everything was it in place I started to test the Web Service and everything was going fine. But as I started to push more and data, at one point the web service started not to work anymore. As soon as the Web Service had less data to return it would works again.</p> <p>To check what was going wrong, I fired up <a href="http://en.wikipedia.org/wiki/Fiddler_%28software%29">fiddler</a> to check the web service response and saw this : <table border="1" cellpadding="0" cellspacing="0"><tbody> <tr> <td width="614" valign="top"> <p>Jsonp1260899050254({"d":{"__type":"……. );jsonp1260899050254(…ErrorMessage":null}});</p> </td> </tr> </tbody></table> </p> <p>As you can see it seemed like my response was cut at one point (always between 16 000 and 17 000 characters) with a ‘)’, then the name of the callback method was added again and finally it was closed correctly.</p> <p>I don’t know what the problem was exactly. I suspect the the streambuffer used in the HttpHandler suggested by Adel Khalil’s was somewhat full at about 16 000 characters. Thus the compliance method would be run twice.</p> <p>Being onsite and needing to fix the problem ASAP I didn’t spent time investigating and rushed into finding a solution. I tried to simplify the compliance HttpModule as much as possible and here is what I come up with: <br /><table border="1" cellpadding="0" cellspacing="0" width="414"><tbody> <tr> <td valign="top"><!-- code formatted by http://manoli.net/csharpformat/ --><br /><pre class="csharpcode"><br /><span class="kwrd">public</span> <span class="kwrd">class</span> JsonHttpModule : IHttpModule<br />{<br /><span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">string</span> JSON_CONTENT_TYPE = <span class="str">"application/json; charset=utf-8"</span>;<br /><br /><span class="kwrd">public</span> <span class="kwrd">void</span> Dispose()<br />{<br />}<br /><span class="kwrd">public</span> <span class="kwrd">void</span> Init(HttpApplication app)<br />{<br /> app.BeginRequest += OnBeginRequest;<br /> app.EndRequest += <span class="kwrd">new</span> EventHandler(OnEndRequest);<br />}<br /><span class="kwrd">public</span> <span class="kwrd">void</span> OnBeginRequest(<span class="kwrd">object</span> sender, EventArgs e)<br />{<br /> HttpApplication app = (HttpApplication)sender;<br /> HttpRequest request = app.Request;<br /> <span class="rem">//Make sure we only apply to our Web Service</span><br /> <span class="kwrd">if</span> (request.Url.AbsolutePath.ToLower().Contains(<span class="str">"MyWS.asmx"</span>))<br /> {<br /> <span class="kwrd">if</span> (<span class="kwrd">string</span>.IsNullOrEmpty(app.Context.Request.ContentType))<br /> {<br /> app.Context.Request.ContentType = JSON_CONTENT_TYPE;<br /> }<br /> app.Context.Response.Write(app.Context.Request.Params[<span class="str">"callback"</span>] + <span class="str">"("</span>);<br /> }<br />}<br /><span class="kwrd">void</span> OnEndRequest(<span class="kwrd">object</span> sender, EventArgs e)<br />{<br /> HttpApplication app = (HttpApplication)sender;<br /> HttpRequest request = app.Request;<br /> <span class="kwrd">if</span> (request.Url.AbsolutePath.ToLower().Contains(<span class="str">"MyWS.asmx"</span>))<br /> {<br /> app.Context.Response.Write(<span class="str">")"</span>);<br /> }<br />}<br />}</pre><br /> </td><br /> </tr><br /></tbody></table><br /></p>As you can see my HttpModule is doing as little as possible:<br /><ul><li>Before generating the response : Add the name of callback from the QueryString parameters and a ‘(‘ to the response if the HttpModule is running for my web Service </li><li>After generating the response : Add ‘);’ at the end of the response if the HttpModule is running for my WebService </li></ul><img style="border: 0px none ; display: inline; margin-left: 0px; margin-right: 0px;" title="image" alt="image" src="http://lh4.ggpht.com/_UjyR4_TTJjc/S1yHRFUHvtI/AAAAAAAAF84/kCgznRV7PKk/image%5B48%5D.png?imgmax=800" width="64" align="left" border="0" height="44" />Simple enough for my problem to go away, moreover it meant less code to maintain in the future.<br /><br /><p> </p>If needed, it is possible to add a switch to make it SOAP and straight JSON compliant, if no callback parameter is given it wouldn’t do anything to the response. It would only take a couple more lines.<br /><br /><h4>Roadblocks #2 : Definitely a matter of size</h4><img style="display: inline; margin-left: 0px; margin-right: 0px;" title="Roadblocks #2 : Definitely a matter of size" alt="Roadblocks #2 : Definitely a matter of size" src="http://lh3.ggpht.com/_UjyR4_TTJjc/S1yHSL66gBI/AAAAAAAAF88/O-qM53dHyNM/image%5B45%5D.png?imgmax=800" width="240" align="right" height="160" /> It could have ended like that, a running ASP.Net JSONP compliant Web Service, but it didn’t. Keeping testing the web service with more and more data, I hit another point where the Web Service seemed not to work.<br /><br /><p>Once again, I called my good friend fiddler for help. It soon became apparent that the server would only return 500 responses. </p><br /><p><img style="border: 0px none ; display: inline;" title="500 http error code" alt="500 http error code" src="http://lh4.ggpht.com/_UjyR4_TTJjc/S1yHSZvGLJI/AAAAAAAAF9A/TX6nhZQf3Y8/clip_image001%5B4%5D.png?imgmax=800" width="138" border="0" height="23" /></p>Http 500 status code means that an <a href="http://www.checkupdown.com/status/E500.html">internal server error</a> happened. So I went searching through my application logs, SharePoint logs, the Windows logs, … but couldn’t the slightest beginning of a reason for my problem.<br />Using the debugger I found out that my Web Service methods were called correctly and that no exceptions were thrown by my code.<a name="_GoBack"></a><br /><br />It was getting weirder and weirder. The response data were correctly generated and returned by my Web Service. I didn’t know exactly what happened but figured that it had to do with the way ASP.Net serialized (‘converted’ if you wish) my response object. As it happened when the size of object increased I started to look for a parameter that would cap the JSONP response size. Such a parameter exists. By default this parameter specify that no response longer than 102 400 character can be serialized to JSONP. For reference you can consult: <a href="http://msdn.microsoft.com/en-us/library/bb763183.aspx">http://msdn.microsoft.com/en-us/library/bb763183.aspx</a><br /><br /><p>It takes place in the web.config as illustrated below:<table border="1" cellpadding="0" cellspacing="0"><tbody><tr><br /> <td width="614" valign="top"><!-- code formatted by http://manoli.net/csharpformat/ --><br /> <pre class="csharpcode"><span class="kwrd"><</span><span class="html">configuration</span><span class="kwrd">></span><br /><span class="kwrd"><</span><span class="html">system.web.extensions</span><span class="kwrd">></span><br /><span class="kwrd"><</span><span class="html">scripting</span><span class="kwrd">></span><br /><span class="kwrd"><</span><span class="html">webServices</span><span class="kwrd">></span><br /><span class="kwrd"><</span><span class="html">jsonSerialization</span> <span class="attr">maxJsonLength</span><span class="kwrd">="102400"</span><span class="kwrd">/></span><br /><span class="kwrd"></</span><span class="html">webServices</span><span class="kwrd">></span><br /><span class="kwrd"></</span><span class="html">scripting</span><span class="kwrd">></span><br /><span class="kwrd"></</span><span class="html">system.web.extensions</span><span class="kwrd">></span><br /><span class="kwrd"></</span><span class="html">configuration</span><span class="kwrd">></span><br /></pre><br /> </td><br /> </tr><br /></tbody></table><br /></p><img style="border: 0px none ; display: inline; margin-left: 0px; margin-right: 0px;" title="image" alt="image" src="http://lh4.ggpht.com/_UjyR4_TTJjc/S1yHRFUHvtI/AAAAAAAAF84/kCgznRV7PKk/image%5B48%5D.png?imgmax=800" width="64" align="left" border="0" height="44" />And here it is, problem solved.<br /><br /><p> </p><br /><br /><p> </p><img style="border: 0px none ; display: inline; margin-left: 0px; margin-right: 0px;" title="image" alt="image" src="http://lh5.ggpht.com/_UjyR4_TTJjc/S1yHTBxQWcI/AAAAAAAAF9M/-VviV28YlPw/image%5B50%5D.png?imgmax=800" width="60" align="left" border="0" height="60" /> Yet I have to admit being upset when I found out the solution to my problem, the fact no error messages where logged anywhere I could found them. How are we supposed to diagnose our problem when the only error message is a 500 Http Error code?<br /><br /><h4>Finally arriving</h4>Here I am, I now have a working WSP that deploys my JSONP web service in my SharePoint Web Application. Using jQuery to consume the Web Service it is even possible to use my application from non SharePoint web pages hosted on other web servers.Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com1tag:blogger.com,1999:blog-28148811.post-81451681167976837242009-09-09T21:50:00.003+02:002010-01-28T12:33:14.617+01:00Retrieve List and View GUIDs with a bookmarklet<p><a href="http://jonathanroussel.com/repo/blogpro/RetrieveListandViewGUIDswithabookmarklet_13272/image.png"><img style="border-width: 0px;" alt="image" src="http://jonathanroussel.com/repo/blogpro/RetrieveListandViewGUIDswithabookmarklet_13272/image_thumb.png" width="166" align="left" border="0" height="75" /></a> </p> <p align="justify">As I am often using SharePoint Designer, I regulary need to get the lists or views guids on my WSS or MOSS sites. Until now I would use SharePoint Manager or access the List or View settings to get the IDs I needed from the URL. Not a big deal but definitely a pain.</p> <p align="justify">I now have a very simple solution to solve this problem, a <a href="http://en.wikipedia.org/wiki/Bookmarklet" target="_blank">bookmarklet</a>. I just drag and drop the following links to the bookmarks bar of my browser and click on these links when I am on a SharePoint List or library display. The IDs are then either Popuped (Use CTRL+C to copy the full popup message on Internet Explorer, selection is possible in Firefox) or wrote on the page. </p> <blockquote> <p><strong>Absolutely no changes are necessary on the server side and you just need to add a bookmark to your browser on the client-side.</strong></p> </blockquote> <p>The first bookmarklet shows a pupup with the IDs looking like</p> <p><a href="http://jonathanroussel.com/repo/blogpro/RetrieveListandViewGUIDswithabookmarklet_13272/image_3.png"></a><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/RetrieveListandViewGUIDswithabookmarklet_13272/image_4.png" width="421" border="0" height="113" /> </p> <p>Drag and drop this link (<a href="javascript:{mI=document.getElementsByTagName('ie:menuitem');for(i=0;i<mI.length;i++){if(mI[i].id.indexOf('ModifyView')!=%20-1)vieItem%20=%20mI[i];}baSt=vieItem.getAttribute('onMenuClick');enLisInd=%20baSt.indexOf('%257D');liI=baSt.substring(baSt.indexOf('%257B')+3,enLisInd);baSt=baSt.substr(enLisInd%20+%203);viI=baSt.substring(baSt.indexOf('%257B')+3,baSt.indexOf('%257D'));alert('List-%20'+liI.replace(/%252D/gi,'-')+'%20-view-%20'+viI.replace(/%252D/gi,'-'));}">View IDs (alert)</a>) to the bookmark tab, it is usually found just under the address bar.</p> <p>The second one will replace the page with the IDs like that</p> <p><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/RetrieveListandViewGUIDswithabookmarklet_13272/image_5.png" width="470" border="0" height="137" /></p> <p>Drag and drop this link (<a href="javascript:{mI=document.getElementsByTagName('ie:menuitem');for(i=0;i<mI.length;i++){if(mI[i].id.indexOf('ModifyView')!=%20-1)vieItem%20=%20mI[i];}baSt=vieItem.getAttribute('onMenuClick');enLisInd=%20baSt.indexOf('%257D');liI=baSt.substring(baSt.indexOf('%257B')+3,enLisInd);baSt=baSt.substr(enLisInd%20+%203);viI=baSt.substring(baSt.indexOf('%257B')+3,baSt.indexOf('%257D'));document.write('List-%20'+liI.replace(/%252D/gi,'-')+'%20VIEW%20'+viI.replace(/%252D/gi,'-'));}">View IDs</a>)for this version</p> <p align="justify">The bookmarklet are simple javascript code that parses the page looking for the Edit View link. They then get the IDs from this link before decoding them. The drawback of my method is that you need to have sufficient permissions to modify the view.</p> <p align="justify">The javascript code is displayed below for your information or if you have some trouble adding the links to your bookmarks with Drag’n Drop.</p> <table width="400" border="0" cellpadding="10" cellspacing="0"><tbody> <tr> <td width="400" valign="top"><span style="font-size:78%;"><em><a href="javascript:{mI=document.getElementsByTagName('ie:menuitem');for(i=0;i<mI.length;i++){if(mI[i].id.indexOf('ModifyView')!= -1)vieItem = mI[i];}baSt=vieItem.getAttribute('onMenuClick');enLisInd= baSt.indexOf('%257D');liI=baSt.substring(baSt.indexOf('%257B')+3,enLisInd);baSt=baSt.substr(enLisInd + 3);viI=baSt.substring(baSt.indexOf('%257B')+3,baSt.indexOf('%257D'));alert('List- '+liI.replace(/%252D/gi,'-')+' -view- '+viI.replace(/%252D/gi,'-'));}">View IDs (alert)</a></em></span> </td> </tr> <tr> <td width="400" valign="top"><em><span style="font-size:78%;"><a href="javascript:{mI=document.getElementsByTagName('ie:menuitem');for(i=0;i<mI.length;i++){if(mI[i].id.indexOf('ModifyView')!= -1)vieItem = mI[i];}baSt=vieItem.getAttribute('onMenuClick');enLisInd= baSt.indexOf('%257D');liI=baSt.substring(baSt.indexOf('%257B')+3,enLisInd);baSt=baSt.substr(enLisInd + 3);viI=baSt.substring(baSt.indexOf('%257B')+3,baSt.indexOf('%257D'));document.write('List- '+liI.replace(/%252D/gi,'-')+' VIEW '+viI.replace(/%252D/gi,'-'));}">View IDs</a></span></em></td> </tr> </tbody></table> <p align="justify">The javascript is pretty nasty for a good reason, Internet Explorer 6 bookmarks are limited at about 500 characters. Even if my scripts aren’t very complex, a 500 characters limit is very short.</p> <p align="justify">Tested on Internet Explorer 6, 8 and Firefox 3 on a MOSS 2007 – SP2 farm in English and French. Please be aware that Internet Explorer will display a security warning when adding the bookmark.</p> <p align="justify"> </p> <p align="center">Hope you enjoy my bookmarklets !</p><p align="center"><br /></p><p style="text-align: left;">Edit : Just so you know, I found a bug in these bookmarlet and just fixed it.<br /></p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com3tag:blogger.com,1999:blog-28148811.post-66953480925295595092009-08-19T22:15:00.007+02:002010-01-28T12:33:31.184+01:00The worm ate my SharePoint homework<p><a href="http://www.flickr.com/photos/haiza/3476661444/"><img src="http://farm4.static.flickr.com/3541/3476661444_1dc00a2076.jpg" width="124" align="left" height="94" /></a> Let me start this post with a question I had to answer today</p> <p> </p> <p> </p> <blockquote> <p>If your SharePoint Web Front End server suddenly loses its connection to the database server. What is the first thing that comes to your mind?</p> </blockquote> <p>In my case, plenty of stuff, from pure hardware breakdown to a very convoluted side effect of my last modification. The latest being a click on “Add a Link” in the navigation settings, I was a bit skeptic about that :) </p><br /><p>Actually, I hadn't even started to imagine the actual cause. After checking the status of the DB server and digging through the event logs, it seemed like there was a problem with some account that had “insufficient privileges”. Opening my favorite AD Explorer (<a href="http://technet.microsoft.com/en-us/sysinternals/bb963907.aspx">AdExplorer by SysInternals</a> actually ;-) ), I checked the service accounts used by MOSS and bingo, they were locked.</p> <p>Telling the client about my findings they found out why quickly. <strong>Some computers were infected by a variant of conflicker</strong>, a worm that would try breaking admins password open using a dictionary attack, thus locking the accounts.</p> <p>So here is today finding:</p> <p> </p> <blockquote> <p>When the WFE loses its connection to the database server, check your antivirus ;-)</p> </blockquote> <p style="font-style: italic; color: rgb(192, 192, 192);" align="justify"><span style="font-size:85%;">Photo : <a href="http://www.flickr.com/photos/haiza/3476661444/" target="_blank">Structure of the influenza virus / Influenza en México 6 credit Hector Aiza @Flickr</a></span></p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com0tag:blogger.com,1999:blog-28148811.post-14915836608543688712009-08-16T19:55:00.006+02:002009-08-16T22:22:07.108+02:00Consuming Search Web Service in SharePoint Designer - the encoding problem<p>The other day I was using the DataFormWebPart (DataViewWebPart) to consume the MOSS Search web service. As I had some advanced parameterization to do, the SharePoint Designer GUI wasn't enough, so I had to modify the encoded QueryXml. You know those stuff looking like :</p> <p> </p> <table style="font-style: italic; color: rgb(153, 153, 153);" width="400" border="0" cellpadding="10" cellspacing="0"><tbody> <tr> <td valign="top" width="400"><span style="font-size:100%;">_x0020_Rank_x002c__x0020_Size_x002c__x0020_Description_x002c__x0020_</span></td> </tr> </tbody></table> <p>As you can see it's a real pleasure to edit such encoded text. So I decided to roll up my sleeves and made a Quick 'nDirty HTML page with some javascript to encode/decode such encoding.</p> <p>Here is the page : <a href="http://www.jonathanroussel.com/unicodec">jonathanroussel.com/unicodec</a></p> <br /><br />Or you can use the iframe below<br /><iframe width="400" height="750" src="http://www.jonathanroussel.com/unicodec/unicodec.html"></iframe>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com0tag:blogger.com,1999:blog-28148811.post-8074126867419035192009-06-09T21:56:00.003+02:002009-06-10T08:28:28.740+02:00SharePoint Lookup Columns on steroids with CAML<p><a title="Nelson's Column by vgm8383" href="http://www.flickr.com/photos/vgm8383/2490312723/" target="_blank"><img align="left" src="http://farm3.static.flickr.com/2285/2490312723_8fd95b19e3_m.jpg" width="120" height="171" /></a> </p> <p>In an <a href="http://blog.jonathanroussel.com/2009/06/lookup-column-and-its-limits.html" target="_blank">earlier post</a> I told you about a <strong>CAML query you could use to add a cross-site lookup column</strong>, pointing on a list from any other site of the same collection.</p> <p></p> <p></p> <p></p> <p align="justify"> </p> <p align="justify"> </p> <p align="justify">No suspens for this post, here is the Query :</p> <table border="0" cellspacing="0" cellpadding="10" width="438"><tbody> <tr> <td valign="top" width="436"><strong><Field Type="Lookup" DisplayName="Office" Required="FALSE" List="{}" WebId="" ShowField="Title" UnlimitedLengthInDocumentLibrary="FALSE" StaticName="Office" Name="Office"/></strong></td> </tr> </tbody></table> <p align="justify">Where List and ShowField specifies the list and list column to lookup from. The WebId is the id of the Web where this list is. </p> <p align="justify">If you take a close look at the Field reference: <a href="http://msdn.microsoft.com/en-us/library/ms437580.aspx">http://msdn.microsoft.com/en-us/library/ms437580.aspx</a> you will notice that the WebId attribute isn’t specified, yet I am using it. Well I obviously didn’t invent this parameter, as I explained in my previous post, this cross site lookup only worked if using a web content type. So I checked the field definition of the working cross site lookup I created using a Document Library template and noticed this parameter using SharePoint Manager 2007 <a href="http://www.codeplex.com/spm">www.codeplex.com/spm</a>.</p> <p align="justify">By using it I can do create a working cross site lookup column without having to create a web content type. A short demo might help you understand how it works:</p> <p align="justify">I have the following site hierarchy:</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointLookupColumnsonsteroidswithCAM_13341/image.png"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="image" align="left" src="http://jonathanroussel.com/repo/blogpro/SharePointLookupColumnsonsteroidswithCAM_13341/image_thumb.png" width="247" height="139" /></a> </p> <p align="justify">I want to add a column in the Phones Directories document library, this column shall be a lookup to the Title column of the Offices List. With standard functionality it’s a no go but let’s try a CAML query to create this column.</p> <p>Assuming that:</p> <ul> <li>SA ID is 460dd869-7508-4eba-8c34-bfeffcc823fc </li> <li>Offices ID is 45BE507B-DF8C-43BC-AF6A-4C05EECA13DA </li> </ul> <p>I know that I should use the following query: </p> <table border="0" cellspacing="0" cellpadding="10" width="438"><tbody> <tr> <td valign="top" width="436"><em><Field Type="Lookup" DisplayName="Office" Required="FALSE" List="{45BE507B-DF8C-43BC-AF6A-4C05EECA13DA}" WebId="460dd869-7508-4eba-8c34-bfeffcc823fc" ShowField="Title" UnlimitedLengthInDocumentLibrary="FALSE" StaticName="Office" Name="Office"/></em></td> </tr> </tbody></table> <p>As PowerShell is my BFF when dealing with SharePoint, I wrote a short script to create this column : </p> <table border="0" cellspacing="0" cellpadding="10" width="438"><tbody> <tr> <td valign="top" width="436"> <p><em># IT Joe – </em><a href="http://blog.jonathanroussel.com/"><em>http://blog.jonathanroussel.com</em></a> <br /><em># One Shot Script - Add a column to a list using a CAML query </em></p> <p><em>[System.Reflection.Assembly]::LoadWithPartialName(”Microsoft.SharePoint”) </em></p> <p><em>$siteurl = "</em><a href="http://moss:81/SB"><em>http://moss:81/SB"</em></a> <br /><em>$mysite=new-object Microsoft.SharePoint.SPSite($siteurl) </em></p> <p><em>if($mysite) <br />{ <br />$web = $mysite.openweb() <br />if($web) <br />{ <br />"WEB : " + $web.name + " / " + $web.title + " @ " + $web.url <br />$list =$web.lists["PhoneDirectories"] <br />if($list) <br />{ <br />"List : " + $list.title <br />$list.Fields.AddFieldAsXml('<Field Type="Lookup" DisplayName="Office" Required="FALSE" List="{45BE507B-DF8C-43BC-AF6A-4C05EECA13DA}" WebId="460dd869-7508-4eba-8c34-bfeffcc823fc" ShowField="Title" UnlimitedLengthInDocumentLibrary="FALSE" StaticName="Office" Name="Office"/>') <br />} <br />$web.dispose() <br />} <br />$mysite.Dispose() <br />}</em></p> </td> </tr> </tbody></table> <p align="justify">After running the script I open an item of the PhoneDirectories library and …. Voila:</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointLookupColumnsonsteroidswithCAM_13341/image_3.png"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointLookupColumnsonsteroidswithCAM_13341/image_thumb_3.png" width="443" height="218" /></a> </p> <p>As you can the Office column takes its value from:</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointLookupColumnsonsteroidswithCAM_13341/image_4.png"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointLookupColumnsonsteroidswithCAM_13341/image_thumb_4.png" width="197" height="179" /></a> </p> <p align="justify">One more remarks, if you try adding a new column “Office2” looking up the same list without the webid with the following CAML query : </p> <table border="0" cellspacing="0" cellpadding="10" width="438"><tbody> <tr> <td valign="top" width="436"><Field Type="Lookup" DisplayName="Office2" Required="FALSE" List="{45BE507B-DF8C-43BC-AF6A-4C05EECA13DA}" ShowField="Title" UnlimitedLengthInDocumentLibrary="FALSE" StaticName="Office2" Name="Office2"/></td> </tr> </tbody></table> <p>You will see that this column works. I can imagine you thinking </p> <p></p> <blockquote> <p align="justify">“Then why did he told us a minute ago to add this undocumented obscure WebId parameter, I bet he invented it to try to look smart. What a fiasco!”</p> </blockquote> <p align="justify">To answer this question I will just let you remove the original Office column and see for yourself if this Office2 column is still working...</p> <p align="justify">Ok, spoiler alert, it won’t work. Seems like SharePoint needs at least one reference to the Web where the list to lookup is. </p> <p align="justify">I don’t know if you will find It usefull but I hope you will like the trick.</p> <p style="font-style: italic; color: rgb(192,192,192)" align="justify"><span style="font-size:85%;">Photo : <a href="http://www.flickr.com/photos/vgm8383/2490312723/" target="_blank">Nelson's Column credit vgm8383 @Flickr</a></span></p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com10tag:blogger.com,1999:blog-28148811.post-89046711264781975892009-06-03T20:29:00.004+02:002009-06-09T21:59:04.852+02:00SharePoint Lookup Column and its limits<p align="justify"><a href="http://www.flickr.com/photos/tma/8906979/" target="_blank"><img alt="Lookup Pop by Tomas" src="http://farm1.static.flickr.com/6/8906979_24a7d697b2_m.jpg" width="206" align="left" height="157" /></a> SharePoint comes with a very nice feature, the possibility to create columns (for lists, libraries metadata) based on lookup on other lists.</p> <p align="justify">While this is very nice, it come with a huge limitation, you can only lookup list on the site where you are creating the column. If it is a site column, you will still be able to use it in subsites but that’s it.</p> <p>If for example you have the following sites/subsites</p> <p><a href="http://jonathanroussel.com/repo/blogpro/LookupColumnanditslimits_1201B/image.png"><img alt="image" src="http://jonathanroussel.com/repo/blogpro/LookupColumnanditslimits_1201B/image_thumb.png" width="193" border="0" height="155" /></a> </p> <p><a href="http://jonathanroussel.com/repo/blogpro/LookupColumnanditslimits_1201B/clip_image002.gif"></a></p> <p align="justify">Where SA, SB, SC, SD are SharePoint Sites (SPWebs) and SB includes a List L1. </p> <p align="justify">There is no Out Of The Box (OOTB) means to create a lookup in SC on L1. In case of need you will still be able to use some cross site solutions available here and there (e.g. : <a href="http://tonybierman.blogspot.com/2008/07/free-custom-cross-site-lookup-column.html">http://tonybierman.blogspot.com/2008/07/free-custom-cross-site-lookup-column.html</a>).</p> <p align="justify"><em>That’s usually where my conclusion would take place, maybe with a bit of ranting against Microsoft for not allowing us to do that in a standard WSS collection. This conclusion might even have ended with a new item being added to my “What I want in Microsoft SharePoint Server 2010?” wish list.</em> </p> <p align="justify">But it isn’t because I stumbled upon an interesting fact: there actually is a way to do that OOTB.</p> <p align="justify">So first create a Site Column in SB, this column shall be a lookup on a L1 field. Now Create a document library in SB, let’s call it DL1. Use the site column you just created in SB. </p> <p align="justify">You can now save DL1 as a library template and finally create a new document library DL2 in SC based on this template.</p> <p>You get something like that:</p> <p><a href="http://jonathanroussel.com/repo/blogpro/LookupColumnanditslimits_1201B/clip_image004.gif"></a></p> <p><a href="http://jonathanroussel.com/repo/blogpro/LookupColumnanditslimits_1201B/image_3.png"></a><a href="http://jonathanroussel.com/repo/blogpro/LookupColumnanditslimits_1201B/image_4.png"><img alt="image" src="http://jonathanroussel.com/repo/blogpro/LookupColumnanditslimits_1201B/image_thumb_3.png" width="240" height="175" /></a> </p> <p align="justify">If you add a document to DL2, you will be able to select a property based on a L1 lookup. If you still can’t believe it, try adding an item to L1 just to make sure it is available in the list of choice in DL2.</p> <p align="justify">I don’t think it is usable in real life but it triggered something in me<strong>. It is clearly possible to lookup a field from another list using only standard features. I then decided to give it a try using CAML to create my lookup field </strong>and guess what <strong>it works very well.</strong> I will give you more details very soon!</p>Edit: More Details in a <a href="http://blog.jonathanroussel.com/2009/06/sharepoint-lookup-columns-on-steroids.html">newer post</a>.<br /><p style="font-style: italic; color: rgb(192, 192, 192);" align="justify"><span style="font-size:85%;">Photo : <a href="http://www.flickr.com/photos/tma/8906979/" target="_blank">Lookup Pop credit Tomas @Flickr</a></span></p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com8tag:blogger.com,1999:blog-28148811.post-40401944653055574432009-05-28T20:46:00.003+02:002009-05-28T20:53:34.455+02:00SharePoint Walktrough - Displaying List Items with their attachments Part 2/2<p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image.png"><img style="border-width: 0px;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_thumb.png" width="218" align="left" border="0" height="82" /></a> </p> <p>Recap</p> <p>The SharePoint Out Of the Box List View Web Part is quite powerful, yet it isn’t able to display the attachments of a List Item. It can show if an item has any attachments (with a nice paper-clip icon) but you won’t be able to download these attachments directly.</p> <p>I presented in <a href="http://blog.jonathanroussel.com/2009/05/sharepoint-walktrouh-displaying-list.html">Part 1 of this walkthrough</a> <strong>how to create a DataView part consuming the Lists.asmx Web Service</strong> in SharePoint Designer to display the elements of a list. We are now going to <strong>display the attachments</strong> of these list elements.</p> <p> To retrieve the attachments URLs we need to add an option to the Web Service Soap query, the “<strong><em>IncludeAttachmentUrls</em></strong>” option (details of the query options is available at <a title="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spquery_properties.aspx" href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spquery_properties.aspx">http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spquery_properties.aspx</a>). We could just open the datasource and change the QueryOptions parameter, that is if the SharePoint WSDL files were correctly defined… As it is not the case and SharePoint Designer itself isn’t perfect, you won’t be able to do that (see <a href="http://blogs.msdn.com/sharepointdesigner/archive/2008/06/20/data-source-issues-and-workarounds.aspx">http://blogs.msdn.com/sharepointdesigner/archive/2008/06/20/data-source-issues-and-workarounds.aspx</a> for reference).</p> <p>But there is a workaround!</p> <h4>4 – Modify the DataSource QueryOptions parameters</h4> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_3.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_thumb_3.png" width="128" align="left" border="0" height="26" /></a>First you need to have <strong>access to the page source</strong>, so let’s switch SharePoint Designer to Split or Code view :</p> <p> In the code, search for the line starting with: “<em>SharePoint:SoapDataSource</em>”. On the same line you shall see something like “ <em></listName></GetListItems></soap:Body>”.</em></p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_4.png"><img style="border-width: 0px;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_thumb_4.png" width="489" border="0" height="27" /></a> </p> <p>As you can see the parameters we defined in the Data Source Gui are found here and guess what, we can modify these parameters from here! So let’s add the parameter requesting the attachments url :</p> <blockquote> <p><queryOptions><QueryOptions><IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls></QueryOptions></queryOptions></p> </blockquote> <p>So that the end of the soap request body looks like :</p> <blockquote> <p></listName><queryOptions><QueryOptions><IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls></QueryOptions></queryOptions></GetListItems></soap:Body></p> </blockquote> <p>Save the page and check the result in the design view :</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_5.png"><img style="border-width: 0px;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_thumb_5.png" width="426" border="0" height="94" /></a> </p> <p>The ows_attachments field now contains the attachments URLs or 0 for list items with no attachments using the following format :</p> <blockquote> <p>;#http://moss/Lists/MyList/Attachments/1/Piece.txt;#http://moss/Lists/MyList/Attachments/1/Piece2.txt;#</p> </blockquote> <p>We still need to make some nice links out of this field. Time to put on your XSL designer gear.</p> <h4>5 – Modify the XSL Presentation</h4> <p>We first create a XSL template to<strong> transform the string</strong> given by the Web Service <strong>into a nice series of picture</strong>. You might use my sample below, paste this piece of code in the XSL part of the aspx page you are editing in SharePoint Designer (maybe just before the node “</xsl:stylesheet>”).</p> <blockquote> <p><xsl:template name="SplitAttachments"> <br /> <xsl:param name="str"/> <br /> <xsl:choose> <br /> <xsl:when test="contains($str,';#')"> <br /> <xsl:variable name="attachmentUrl" select="substring-before($str,';#')"/> <br /> <xsl:if test="string-length($attachmentUrl) != 0"> <br /> <a href="{$attachmentUrl}"><img style="border:0px" src="/_layouts/images/attach.gif" alt='Open'/></a> <br /> </xsl:if> <br /> <xsl:call-template name="SplitAttachments"> <br /> <xsl:with-param name="str" select="substring-after($str,';#')" /> <br /> </xsl:call-template> <br /> </xsl:when> <br /> <xsl:otherwise> <br /> </xsl:otherwise> <br /> </xsl:choose> <br /></xsl:template></p> </blockquote> <p>This XSL template uses a recursive template to parse the attachments and generate corresponding links and pictures.</p> <p>Now replace </p> <blockquote> <p><xsl:value-of select="@ows_Attachments"/></p> </blockquote> <p>By</p> <blockquote> <p><xsl:call-template name="SplitAttachments"> <br /><xsl:with-param name="str" select="@ows_Attachments" /> <br /></xsl:call-template></p> </blockquote> <p>And you should see this :</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_6.png"><img style="border-width: 0px;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_thumb_6.png" width="423" border="0" height="137" /></a> </p> <p>The paper clip icon you see are actually pointing to the attachments.</p> <h4>6 – Pimp up my Data View</h4> <p>At this point our Data View Web Part works ok but isn't as nice as you might want it to be.</p> <p>As an example you might want to change these paper clips icons with icons representing the file type. The good news is that the XSL extension provided by WSS (default prefix used by SharePoint Designer is DDWRT) can handle this through a <strong>MapToIcon template</strong>. If you give a file extension to this template, it will return the icon filename corresponding to this filetype.</p> <p>Using the substring-after method to get the filetype we can imagine replacing :</p> <blockquote> <p>/_layouts/images/attach.gif</p> </blockquote> <p>By</p> <blockquote> <p>/_layouts/images/{ddwrt:MapToIcon('',substring-after($attachmentUrl,'.'))}</p> <p> </p> </blockquote> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_7.png"><img style="border-width: 0px;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11CE8/image_thumb_7.png" width="285" align="left" border="0" height="97" /></a>Now save the file and check the result :</p> <p> </p> <p> </p> <p>It still isn't perfect but from this point on things will be much easier to improve if you know your HTML and a bit of XSL.</p> <h4>7 – Conclusion </h4> <p>That’s it, you have got a functional Web Part to display your List. </p> <p>Using this method you can specify every parameters of the GetListItems method, as an example the ViewName parameter can prove usefull to filter items. If you need to test your parameter I would suggest you to try soapui.org.</p> <p>You can of course export this web part to put it another page, even on another page of another SharePoint farm (in this case, you will have to use the basic authentication mode unless kerberos authentication can do the trick). If you want to display another list you can just export the WebPart and edit the file before reimporting it. This might prove very useful to put this web part on a publication page as these pages can’t be edited using SharePoint Designer.</p> <p align="center">If you need more details you can contact me by leaving a comment or using the "IM Me" box on the right of this page.</p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com27tag:blogger.com,1999:blog-28148811.post-14257169107729397442009-05-28T20:28:00.003+02:002009-05-28T20:53:17.473+02:00SharePoint Walktrough - Displaying List Items with their attachments Part 1/2<p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb.png" width="218" align="left" border="0" height="82" /></a> The SharePoint Out Of the Box List View Web Part is quite powerful, yet it isn’t able to display the attachments of a List Item. It can show if an item has any attachments (with a nice paper-clip icon) but you won’t be able to download these attachments directly. As with most SharePoint limitation, there is a workaround. Drasko Popovic wrote about a JavaScript based workaround on CodeProject you might want to check out at <a href="http://www.codeproject.com/KB/sharepoint/DataViewAttachments.aspx">http://www.codeproject.com/KB/sharepoint/DataViewAttachments.aspx</a>.</p> <p>In this post I want to presents you another workaround where all processing are done server-side with a single Web Service call (Lists.asmx). You will need SharePoint Designer 2007 (freely downloadable since the 2<sup>nd</sup> April 2009 at <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=baa3ad86-bfc1-4bd4-9812-d9e710d44f42&displaylang=en">http://www.microsoft.com/downloads/details.aspx?FamilyID=baa3ad86-bfc1-4bd4-9812-d9e710d44f42&displaylang=en</a> ) and of course a MOSS or WSS instance.</p> <p>As this walkthrough is pretty long for a blog post, it is split into two parts. If you already how to create a Data View web part to display the elements of a list through calls to the Lists.asmx web service, I would suggest you to move to <a href="http://blog.jonathanroussel.com/2009/05/sharepoint-walktrouh-displaying-list_28.html">part 2 of this walkthrough</a>.</p> <h4>0 – Principle/Rationale</h4> <p>We have a list in a SharePoint site and want to display the titles of this list’s elements along with direct links to their attachments.</p> <p>We are going to create a Data View Web Part using SharePoint Designer, this Data View will consume the SharePoint Web Service to get the items of a list along with their attachments. The data view will display these items using a XSL we will define.</p> <p>As a bonus this method will allows us to display the list items on a different SharePoint site or collection than the list itself.</p> <h4>1 – Create or Open a page</h4> <p>In SharePoint Designer after opening your site, either open an existing page or create a new one. I choose this last option:</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_3.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_3.png" width="429" border="0" height="251" /></a> </p> <p>Make some room for our content in the PlaceHolderMain zone of the page by creating a custom content.</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_4.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_4.png" width="473" border="0" height="138" /></a> </p> <p>Adding a Web Part zone isn’t mandatory but I strongly recommend it at this point. Click in the new Custom Content Zone you created in the design view, then click Insert|SharePoint Controls| Web Part Zone.</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_5.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_5.png" width="396" border="0" height="267" /></a> </p> <p>You should get something looking like that in the Design View:</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_6.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_6.png" width="425" border="0" height="96" /></a> </p> <p>SharePoint Designer is sometimes quite buggy, saving frequently from this point on might be a good idea. You can save the page wherever you want to. If you are creating multiple custom pages, creating a dedicated Document Library to hold these pages is a good idea; such a library already exists if you have activated the publication feature.</p> <h4>2 – Create a Web Service Data Source</h4> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_7.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_7.png" width="200" align="left" border="0" height="72" /></a>The page is now ready to host our Data View web part. Open the Data Source view by clicking Data View| Manage Data Sources.</p> <p> </p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_8.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_8.png" width="157" align="right" border="0" height="66" /></a>Choose to connect to a web service:</p> <p> </p> <p>In the Service Description Location enter: <a href="http://sp_site_url/_vti_bin/lists.asmx">http://SP_SITE_URL/_vti_bin/lists.asmx</a>, then click connect and choose the GetListItems operation:</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_9.png"></a><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_10.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_9.png" width="439" border="0" height="325" /></a> </p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_11.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_10.png" width="244" align="left" border="0" height="137" /></a>Double click on the listName parameter and enter the name or guid (between brackets {}) of your list.</p> <p> </p><p><br /></p><p><br /></p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_12.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_11.png" width="243" align="right" border="0" height="88" /></a>Validate the Data Source Properties and check that it is working correctly by trying to see the data returned by this data source:</p> <p> </p> <p>If a new panel opens with the list data, it means it’s working.</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_13.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_12.png" width="183" border="0" height="244" /></a> </p> <h5>Troubleshooting:</h5> <p>If it isn’t working you will be presented with an enigmatic error message giving you absolutely no details:</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_14.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_13.png" width="244" border="0" height="139" /></a> </p> <p>This can be caused by numerous reasons you want to check:</p> <ul> <li>The name or guid of the list is invalid</li> <li>You tried to specify other parameters of the Web Service such as QueryOptions or ViewFields. These parameters can’t be specified at this point as the SharePoint Designer Team Blog attests it (<a href="http://blogs.msdn.com/sharepointdesigner/archive/2008/06/20/data-source-issues-and-workarounds.aspx">http://blogs.msdn.com/sharepointdesigner/archive/2008/06/20/data-source-issues-and-workarounds.aspx</a>). We will modify those latter on.</li> <li>Problem of authentication, I need to investigate this problem but it seems like you sometimes can’t use the integrated authentication even when using a single WFE. In this case you have to change the Web Service Authentication method to basic and to specify a domain account that has the appropriate permission to read the list items and contact the web service.</li> </ul> <h5>Changing the Web Service authentication:</h5> <p>Open the Data Source properties</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_15.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_14.png" width="301" border="0" height="177" /></a> </p> <p>Open the login tab and choose basic authentication:</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_16.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_15.png" width="354" border="0" height="161" /></a> </p> <p>Save the details and try again to retrieve the data.</p> <h4>3 – Create the Data View Web Part</h4> <p>We now have a working Data Source, let’s create a web part to display it.</p> <p>In the Data Source Details, select the ows_LinkTitle and ows_Attachments properties and choose insert this field as a Multiple Item View (Note: you might need to select the Web Part zone in the design view of the page beforehand).</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_17.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_16.png" width="238" border="0" height="224" /></a> </p> <p>You shall now see something like that in the design view.</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_18.png"><img style="border: 0px none ;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SharePointWalktrouhDisplayingListItemswi_11DA6/image_thumb_17.png" width="244" border="0" height="65" /></a> </p> <p>We know have a very basic Data View Web Part but as you may have noticed the ows_attachments fields just display the number of attachments but not the actual links to these attachments.</p> <p>We will see in <a href="http://blog.jonathanroussel.com/2009/05/sharepoint-walktrouh-displaying-list_28.html">part 2 of this walkthrough </a>how to solve this.</p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com22tag:blogger.com,1999:blog-28148811.post-87438541096527888362009-04-25T12:39:00.002+02:002009-04-25T12:42:32.240+02:00Quick, Easy and Free WAN emulation with WANem<a href="http://www.flickr.com/photos/herrolm/2820552527/" target="_blank"><img alt="Fibre Channel cable By Herrolm @ Flickr" src="http://farm4.static.flickr.com/3161/2820552527_4255e0b5dd.jpg?v=0" align="left" width="175" height="132" /></a> <p>A client recently asked us to deploy a MOSS based intranet over multiple geographical sites. The gist of it is to have a SharePoint farm in France and a second one in the US, with this dual-farms setup being as transparent as possible to the user. This in itself represents quite a challenge and as such will be the subject of a post once the project is finished. </p> <p>We, of course, tried our different options in a mock up environment consisting of several virtual machines hosted on a single VMVare server instance. </p> <p>As such, this set-up obviously lacked in representativeness of the actual environment. <strong>Being geographically dispersed the servers are not able to communicate in real life as efficiently as they can in the mock-up environment. They are indeed connected over WAN with round trip latencies over 100 milliseconds</strong>. We fiddled a bit with VMWare server options trying to find an option to limit the virtual network speeds, without any success. It would seems like VMWare ESX is better suited for this kind of WAN emulation but ESX wasn’t an option, especially considering that we had no certitude about its features regarding WAN emulation.</p> <p> </p> <blockquote> <p><b>But wait, there is a free, open-source, easy –to-install, easy-to-use option available. Let me introduce you to WANem (for Wide Area Network Emulator).</b> It’s a Linux live-cd (The numerous 2.09 % of linux visitors over the past month on this blog might be interested to know that it is based on Knoppix) bundled with the WANEm software itself that Tata Consulting provides us with at <a style="font-weight: normal;" href="http://wanem.sourceforge.net/">http://wanem.sourceforge.net</a>.</p> </blockquote> <p>As it is a <span style="font-weight: bold;">live-cd, there is absolutely no installation to be done</span>. Just boot up, select DHCP or enter the network information and you are good to go. You can then select from a direct-to-the-point interface what bandwith limitations and latencies you want to enforce. An advanced mode will even allow you to specify numerous others parameters such as the packet loss ratio. The only other piece of configuration you’ll need to do is to specify routes on your servers so that the packets actually go through the WANEm machine.</p> <p><a href="http://jonathanroussel.com/repo/blogpro/QuickEasyandFreeWANemulationwithWANem_B1E2/clip_image002.jpg"><img style="border: 0px none ;" alt="WANEm Web Console in Advanced Mode" src="http://jonathanroussel.com/repo/blogpro/QuickEasyandFreeWANemulationwithWANem_B1E2/clip_image002_thumb.jpg" border="0" width="427" height="335" /></a></p> <p>So, we have a very easy-to-use, functional software for free! Seems great! Too good to be true, wait, it’s not all; <span style="font-weight: bold;">the documentation included is a delight.</span> I don’t know if it’s the same for you, but I have spent hours trying to make some open-source software work because of poor or inexistent documentation. Don’t get me wrong, open-source is great but sometimes the greatness of the piece of the software itself is at the cost of the documentation.</p> <p><a href="http://jonathanroussel.com/repo/blogpro/QuickEasyandFreeWANemulationwithWANem_B1E2/clip_image004.jpg"><img style="border: 0px none ;" alt="The WANEM Web console in basic mode" src="http://jonathanroussel.com/repo/blogpro/QuickEasyandFreeWANemulationwithWANem_B1E2/clip_image004_thumb.jpg" border="0" width="438" height="171" /></a></p> <p>Anyway, they probably tought it wasn’t enough so they put a nice cherry at the top of the cake and created a <span style="font-weight: bold;">VMWare server appliance with WANEm configured</span>.</p> <p>Finally because everything ought to have a default, WANEm is only available as a live-cd, even when provided in a virtual machine. Therefore the configuration isn’t persisted and you will have to reenter it every time you reboot the computer/vm, no big deal considering the few steps involved. It might even change soon as I read on their forum that a guy might have actually installed it on a drive (virtual or physical).</p> <p>So if you need to emulate a WAN and don’t want/need to invest in an expensive Hardware solution, I strongly recommend you to give WANem a try at <a href="http://wanem.sourceforge.net/">http://wanem.sourceforge.net</a>.</p> <p> </p> <p><em><span style="color: rgb(112, 112, 112);">Fiber Channel photo courtesy of </span></em><a href="http://www.flickr.com/photos/herrolm/2820552527/" target="_blank"><em><span style="color: rgb(112, 112, 112);">Herrolm @ Flickr</span></em></a></p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com1tag:blogger.com,1999:blog-28148811.post-81985681774717036762009-04-17T19:27:00.002+02:002009-04-17T19:38:25.240+02:00Sorting / Filtering SharePoint RSS feeds<p><a href="http://www.flickr.com/photos/photopia/455572466/" target="_blank"><img alt="Really, REALLY BIG RSS feed button by photopia / HiMY SYeD on flickr.com" src="http://farm1.static.flickr.com/241/455572466_19166858d6_o.gif" align="left" /></a> Ever wondered if it was possible to sort or filter the automatically generated SharePoint RSS feeds? Well I did and, as a matter of fact, I found a solution. The idea is very simple, you create the view that will filter or sort your list elements according to your needs. You then take the guid of your view and append it to the feed URL.</p> <p>Et Voila !</p> <p>Here is an example, let’s say I have a Task List (screenshot from a French MOSS farm, I am sure you’ll get the idea anyway) with some items pending, other finished. This status is defined in a “State” (Etat) column.</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SortingFilteringSharePointRSSfeeds_1115A/image.png"><img style="border-width: 0px;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SortingFilteringSharePointRSSfeeds_1115A/image_thumb.png" width="406" border="0" height="168" /></a> </p> <p>I first create two views filtering on the Etat column. One returns the pending elements, the other returns the finished elements.</p> <p>I then take note of the guid of my two views (Editing the views and extracting the &View=….. part of the URL does the trick).</p> <p>After making sure that RSS feeding is activated for my task list, I can go check the RSS feed at :</p> <p><a href="http://myserver/_layouts/listfeed.aspx?List=a4a88bd0%2Ddf29%2D4f54%2Da924%2D195be47346ed">http://MyServer/_layouts/listfeed.aspx?List=a4a88bd0%2Ddf29%2D4f54%2Da924%2D195be47346ed</a></p> <p>The results as displayed by IE7 looks like :</p> <p><a href="http://jonathanroussel.com/repo/blogpro/SortingFilteringSharePointRSSfeeds_1115A/image_3.png"><img style="border-width: 0px;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SortingFilteringSharePointRSSfeeds_1115A/image_thumb_3.png" width="286" border="0" height="468" /></a> </p> <p>All the items are displayed whatever their status but let’s say that I want to see only the elements pending, so that I know what I need to work on. I just append "&View=<em><VIEW_GUID></em>" to the URL and here is the result :</p> <p><a href="http://myserver/_layouts/listfeed.aspx?List=a4a88bd0%2Ddf29%2D4f54%2Da924%2D195be47346ed&View=%7B9F3ACEAB%2D75DF%2D4C04%2D83C2%2D3A5733A6CA31%7D">http://MyServer/_layouts/listfeed.aspx?List=a4a88bd0%2Ddf29%2D4f54%2Da924%2D195be47346ed&View=%7B9F3ACEAB%2D75DF%2D4C04%2D83C2%2D3A5733A6CA31%7D</a></p> <p><a href="http://jonathanroussel.com/repo/blogpro/SortingFilteringSharePointRSSfeeds_1115A/image_4.png"><img style="border-width: 0px;" alt="image" src="http://jonathanroussel.com/repo/blogpro/SortingFilteringSharePointRSSfeeds_1115A/image_thumb_4.png" width="307" border="0" height="247" /></a> </p> <p>By the way, I only tested this on a MOSS 2007 SP1 install. I would be interested to know if it works with WSS as well.</p> <p>I wonder if this is documented anywhere as I stumbled upon this feature by pure chance ?</p> <p>RSS picture credit <a href="http://www.flickr.com/photos/photopia/455572466/" target="_blank">Photopia on flickr</a></p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com6tag:blogger.com,1999:blog-28148811.post-16773578689948425272009-04-05T17:13:00.003+02:002009-05-20T21:47:04.797+02:00Thinking of copying a locked SharePoint site collection ? Think twice !<p><a href="http://lh6.ggpht.com/_UjyR4_TTJjc/SdjKf1SuMCI/AAAAAAAAFb0/uNMT4JAVATs/s1600-h/clip_image002%5B7%5D%5B3%5D.jpg"><img style="border: 0px none ;" alt="clip_image002[7]" src="http://lh4.ggpht.com/_UjyR4_TTJjc/SdjKgYD6R4I/AAAAAAAAFb4/Ke-lhA8iY94/clip_image002%5B7%5D_thumb%5B1%5D.jpg?imgmax=800" width="244" align="left" border="0" height="123" /></a>I recently had to copy a locked SharePoint site collection from one farm to another farm. I soon realized this wasn’t such a great idea especially if the farms aren’t in the same AD domain. Here is a quick recap of what I noticed after a few more investigatory steps.</p> <p>Eager readers will eagerly jump to the <a href="http://www.blogger.com/post-edit.g?blogID=28148811&postID=1677357868994842527#FinalConlusion">final conclusion.</a></p> <p><b></b></p> <h4>Copying though stsadm backup/restore</h4> <p>Let’s try copying this site collection with the stsadm backup and restore commands. Both farms are MOSS RTM farms.</p> <p>The backup worked smoothly. The restore is a total disaster (“Additions to this Web site have been blocked. Please contact the administrator to resolve this problem.”) :</p> <p><a href="http://lh3.ggpht.com/_UjyR4_TTJjc/SdjKhDIusEI/AAAAAAAAFb8/S4KdDHVBh3k/s1600-h/clip_image002%5B6%5D.jpg"></a></p> <p><a href="http://lh4.ggpht.com/_UjyR4_TTJjc/SdjKhslBSDI/AAAAAAAAFcA/UQQAyWTvFko/s1600-h/screenshot.1%5B13%5D.jpg"><img style="border: 0px none ;" alt="screenshot.1" src="http://lh4.ggpht.com/_UjyR4_TTJjc/SdjKiT_yJfI/AAAAAAAAFcE/YdL5tVKpHMw/screenshot.1_thumb%5B13%5D.jpg?imgmax=800" width="429" border="0" height="79" /></a> </p> <p>The weirder part is that the collection is visible in the central administration but it seems totally messed up. No way to delete it from the Central Adminsitration. The stsadm deletesite command returns the “Additions to this Web site have been blocked. Please contact the administrator to resolve this problem.” error.</p> <p>Conclusion : Not a good idea ! Might actually works using the trick I finally used, see below.</p> <h4>Copying using a SQL Server backup</h4> <p>Seemed like today would be another day battling with SharePoint. But I wasn't short on idea. Indeed My locked site collection was alone in its content DB, therefore I was able to use a backup to restore the collection on my target farm.</p> <p>The restore wentsmoothly. I was starting to believe it was actually going to be easy!</p> <p>And then my frail hopes were cruelly shattered by the terrible SharePoint truth when I opened up the Central Administration to change the collection administrator.</p> <p>The first obvious step is to select the site collection but when selecting the site collection in the “Select Site Collection” popup, none of the collection details would appear on the right. </p> <p><a href="http://lh3.ggpht.com/_UjyR4_TTJjc/SdjKi1ErmEI/AAAAAAAAFcI/XchzjG-yEu0/s1600-h/clip_image004%5B4%5D.jpg"><img style="border: 0px none ;" alt="clip_image004" src="http://lh3.ggpht.com/_UjyR4_TTJjc/SdjKjmPETNI/AAAAAAAAFcM/iWVsrszz3i0/clip_image004_thumb%5B1%5D.jpg?imgmax=800" width="420" border="0" height="148" /></a></p> <p>Huh ? I tried validating the popup anyway and was presented with this screen:</p> <p><a href="http://lh5.ggpht.com/_UjyR4_TTJjc/SdjKkAscrHI/AAAAAAAAFcQ/cJ2uY9qlPPs/s1600-h/clip_image006%5B4%5D.jpg"><img style="border: 0px none ;" alt="clip_image006" src="http://lh3.ggpht.com/_UjyR4_TTJjc/SdjKlPpm0yI/AAAAAAAAFcU/TWdEHmXU21w/clip_image006_thumb%5B1%5D.jpg?imgmax=800" width="441" border="0" height="186" /></a></p> <p>It seemed just as if I had selected nothing, yet the adress bar contained the id of the content database : </p> <p><a href="http://lh6.ggpht.com/_UjyR4_TTJjc/SdjKmVlcM8I/AAAAAAAAFcY/YkHcg3eprz0/s1600-h/clip_image008%5B11%5D.jpg"><img style="border: 0px none ;" alt="clip_image008" src="http://lh6.ggpht.com/_UjyR4_TTJjc/SdjKm64mUhI/AAAAAAAAFcc/0IEBa4N_SQg/clip_image008_thumb%5B8%5D.jpg?imgmax=800" width="462" border="0" height="38" /></a></p> <p>Trying to unlock this site collection would produce kind of the same result.</p> <p>I then realized that the farm administrator had no right on the collection. He indeed had no permissions on the collection when it was backuped. Lucky me, the farms were part of the same domain, therefore I tried a quick and dirty fix, I added the original farm administrator to the target farm administrator group and logged in the Central Adminsitration with this administrator.</p> <p>It was a relief to be able to see the details of the collection. Thou shan’t prevail over me SharePoint ! </p> <p>But once again, I underestimated my adversary which quickly retaliated with a now too common “Additions to this Web site have been blocked” when I tried changing the collection administrator.</p> <p><a href="http://lh6.ggpht.com/_UjyR4_TTJjc/SdjKoFoR14I/AAAAAAAAFcg/gqPY4plMUbc/s1600-h/clip_image010%5B3%5D.jpg"><img style="border-width: 0px;" alt="clip_image010" src="http://lh5.ggpht.com/_UjyR4_TTJjc/SdjKoyRB7YI/AAAAAAAAFck/X9hPHnvlqfQ/clip_image010_thumb.jpg?imgmax=800" width="244" border="0" height="123" /></a></p> <p>But victory was mine at long last when I unlocked the collection while logged in with the original farm administrator account on the target farm. After this step I was able to change the collection administrator to the target farm administrator as I intended from the beginning. </p> <p>Conclusion : It works, but both farms have to be in the same AD domain</p> <h4>Final Conclusion<a name="FinalConclusion"> </a></h4> <p>If possible I would advise you to unlock the site collection before proceeding with the copy. If it isn’t possible, I hope both of your farms are part of the same AD domain, otherwise good luck! Please keep me posted if the powers that be are you on your side.</p> <p>By the way, for those of you thinking that I should have tried the stsadm export command, one simply can’t export a locked site collection this way. </p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com4tag:blogger.com,1999:blog-28148811.post-37509629818298775572009-03-23T21:20:00.008+01:002011-03-29T09:53:12.666+02:00IIS 5 and 6 time-taken field<p><a href="http://lh3.ggpht.com/_UjyR4_TTJjc/ScfvEtqVx1I/AAAAAAAAFbs/oe6f85A804E/s1600-h/IIS_time_taken%5B14%5D.png"><img style="border: 0px none ;" alt="IIS_time_taken" src="http://lh4.ggpht.com/_UjyR4_TTJjc/ScfvF7NFrtI/AAAAAAAAFbw/4teUskoX5oA/IIS_time_taken_thumb%5B12%5D.png?imgmax=800" width="253" align="left" border="0" height="205" /></a>While checking the performance problem a client was having with a legacy ASP.NET 1.1 application (yep, I am still young enough to call a 6 years old system, legacy J ), I asked myself what seems like a basic question. </p><p><b>Does the time-taken column in IIS 5 logs takes into account the network time ? </b></p><p>That is, Is the stop watch stopped when the response is ready or when the last TCP acknowledge is received from the client. After googling for a while I was quite disappointed by the lack of information regarding this specific column. The only useful information I found concerned IIS 6 and were …hum, let’s just say that Microsoft doesn’t seems to be able to make up its mind about this field:</p><p>According to :<a href="http://support.microsoft.com/kb/944884">http://support.microsoft.com/kb/944884</a></p><blockquote><p><b><i>Beginning in IIS 6.0, the time-taken field typically includes network time.</i></b><i> Before HTTP.sys logs the value in the time-taken field, HTTP.sys usually waits for the client to acknowledge the last response packet send operation or HTTP.sys waits for the client to reset the underlying TCP connection. Therefore, when a large response or large responses are sent to a client over a slow network connection, the value of the time-taken field may be more than expected.</i></p></blockquote><p>According to :<a href="http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/676400bc-8969-4aa7-851a-9319490a9bbb.mspx?mfr=true">http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/676400bc-8969-4aa7-851a-9319490a9bbb.mspx?mfr=true</a></p><blockquote><p><i>For the time-taken field, the client-request timestamp is initialized when HTTP.sys receives the first byte, but before HTTP.sys begins parsing the request. The client-request timestamp is stopped when the last IIS send completion occurs. <b>Time taken does not reflect time across the network</b>. The first request to the site shows a slightly longer time taken than other similar requests because HTTP.sys opens the log file with the first request.</i></p></blockquote><p>Perplexed, I figured out I could know the answer for sure by firing up Fiddler and comparing Fiddler time with the value of the time-taken columns in IIS log. I had limited access to the client environment but managed to get some measures nonetheless. Once again, it was a dead-end, the Fiddler times were sometimes higher than the IIS log time, sometimes lower. </p><p>That’s when I decided to contact the Microsoft Partner Support.</p><p>The definite answer they gave me for the time-taken field in IIS 5 logs is:</p><blockquote><p><strong>Since the calculation includes the time for the acknowledgement from the client, it may be skewed by any network latency issues.</strong></p></blockquote><p>The not so definite answer the support gave me for the IIS 6 time-taken field is that after checking the source code, the network time is not included in the time-taken field. However they also say that that if the request is aborted during its execution, no value are logged for the request; Therefore it would seems like IIS 6 waits for the last ACK to log BUT it doesn’t log the network. And that would be why the public available information is as clear as mud.</p><p>I hope it helps.</p><p><br />
</p><p style="font-weight: bold;">Edit : 29/06/2009</p><p>A reader (<span style="font-weight: bold;">thank you Joe</span>) pointed out to me that the <a href="http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/676400bc-8969-4aa7-851a-9319490a9bbb.mspx?mfr=true">http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/676400bc-8969-4aa7-851a-9319490a9bbb.mspx?mfr=true</a> article as been updated with the following :</p><p></p><blockquote><p>This is no longer true for II6, and you can check the KB94483. IIS TIME-TAKEN field takes into account the last ACK from the answer to the response, so in fact does reflect time across the network. There is only 2 exceptions for this:</p><ul><li>The response size is less than or equal to 2 KB, and the response size is from memory.</li>
<li>TCP buffering is used.</li>
</ul></blockquote>So problem solved, but if anyone find the trace of the KB94483 mentionned, let me know because I can't !Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com4tag:blogger.com,1999:blog-28148811.post-15260977317719473182009-01-18T19:26:00.005+01:002011-05-10T13:35:42.075+02:00SharePoint : Search using « This Site » or “This List” scope returning no results<p>I met a problem with the Search scope on a MOSS 2007 farm the other day that I thought was worth blogging about.</p><p><strong>On all the content sites of our farm, the “All Sites” scope worked as expected, but the “This Site” or “This List” search scopes wouldn’t return a single result.</strong> </p><p>There are several reasons that can explains this problem according to this technet forum thread (<a href="http://social.technet.microsoft.com/Forums/en-US/sharepointsearch/thread/906045d8-8782-4c39-be1b-7632f7239019/#page:1">http://social.technet.microsoft.com/Forums/en-US/sharepointsearch/thread/906045d8-8782-4c39-be1b-7632f7239019/#page:1</a>), in our case the problem was due to a difference between the Content Source defined for the crawl and the default zone defined in the Alternate Access mapping.</p><p>Our Alternate Access Mapping for this zone was defined as follow:</p><table width="400" border="1" cellpadding="2" cellspacing="0"><tbody>
<tr> <td valign="top" width="133">Private URL</td> <td valign="top" width="133">Zone</td> <td valign="top" width="133">Public URL</td> </tr>
<tr> <td valign="top" width="133">http://hostname</td> <td valign="top" width="133">Default</td> <td valign="top" width="133">http://hostname</td> </tr>
<tr> <td valign="top" width="133">http://intra.dnsname.com</td> <td valign="top" width="133">Intranet</td> <td valign="top" width="133">http://intra.dnsname.com</td> </tr>
</tbody></table><p>And we used http://intra.dnsname.com as the start address for the crawl.</p><p><strong>We tried changing the content source start address from </strong><strong>http://intra.dnsname.com</strong><strong> to </strong><strong>http://hostname</strong><strong>, resetted the crawl content and launched a full crawl and that was it. The “This Site” and list scopes worked perfectly from then on. </strong></p><p>That could have been it, except that this change caused another problem. Before this modification we had no trouble with links URL, I mean if I used http://intra.dnsname.com to reach the site, all the links in the pages would use this dns name, not the hostname. After the modification of the content source however, some search results would sometimes be presented with the hostname in the url instead of the dns name.</p><p>To solve that problem we changed the Alternate Acces Mapping configuration to:</p><table width="401" border="1" cellpadding="2" cellspacing="0"><tbody>
<tr> <td valign="top" width="133">Private URL</td> <td valign="top" width="133">Zone</td> <td valign="top" width="133">Public URL</td> </tr>
<tr> <td valign="top" width="133">http://hostname</td> <td valign="top" width="133">Default</td> <td valign="top" width="133">http://intra.dnsname.com</td> </tr>
<tr> <td valign="top" width="133">http://intra.dnsname.com</td> <td valign="top" width="133">Default</td> <td valign="top" width="133">http://intra.dnsname.com</td> </tr>
</tbody></table><p></p><p>Voila! The Site and List scopes are working and the URL are always based on the DNS name when someone uses the DNS name to reach to site.</p><p>By the way, you might find this article about Alternate Access Mapping very useful: <a href="http://blogs.msdn.com/sharepoint/archive/2007/03/06/what-every-sharepoint-administrator-needs-to-know-about-alternate-access-mappings-part-1.aspx">http://blogs.msdn.com/sharepoint/archive/2007/03/06/what-every-sharepoint-administrator-needs-to-know-about-alternate-access-mappings-part-1.aspx</a></p>Joehttp://www.blogger.com/profile/16961575902853772221noreply@blogger.com11