Wednesday, September 09, 2009

Retrieve List and View GUIDs with a bookmarklet

image

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.

I now have a very simple solution to solve this problem, a bookmarklet. 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.

Absolutely no changes are necessary on the server side and you just need to add a bookmark to your browser on the client-side.

The first bookmarklet shows a pupup with the IDs looking like

image

Drag and drop this link (View IDs (alert)) to the bookmark tab, it is usually found just under the address bar.

The second one will replace the page with the IDs like that

image

Drag and drop this link (View IDs)for this version

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.

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.

<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>
<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>

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.

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.

Hope you enjoy my bookmarklets !


Edit : Just so you know, I found a bug in these bookmarlet and just fixed it.

Wednesday, August 19, 2009

The worm ate my SharePoint homework

Let me start this post with a question I had to answer today

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?

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 :)


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 (AdExplorer by SysInternals actually ;-) ), I checked the service accounts used by MOSS and bingo, they were locked.

Telling the client about my findings they found out why quickly. Some computers were infected by a variant of conflicker, a worm that would try breaking admins password open using a dictionary attack, thus locking the accounts.

So here is today finding:

When the WFE loses its connection to the database server, check your antivirus ;-)

Photo : Structure of the influenza virus / Influenza en México 6 credit Hector Aiza @Flickr

Sunday, August 16, 2009

Consuming Search Web Service in SharePoint Designer - the encoding problem

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 :

_x0020_Rank_x002c__x0020_Size_x002c__x0020_Description_x002c__x0020_

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.

Here is the page : jonathanroussel.com/unicodec



Or you can use the iframe below

Tuesday, June 09, 2009

SharePoint Lookup Columns on steroids with CAML

In an earlier post I told you about a CAML query you could use to add a cross-site lookup column, pointing on a list from any other site of the same collection.

 

 

No suspens for this post, here is the Query :

<Field Type="Lookup" DisplayName="Office" Required="FALSE" List="{}" WebId="" ShowField="Title" UnlimitedLengthInDocumentLibrary="FALSE" StaticName="Office" Name="Office"/>

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.

If you take a close look at the Field reference: http://msdn.microsoft.com/en-us/library/ms437580.aspx 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 www.codeplex.com/spm.

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:

I have the following site hierarchy:

image

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.

Assuming that:

  • SA ID is 460dd869-7508-4eba-8c34-bfeffcc823fc
  • Offices ID is 45BE507B-DF8C-43BC-AF6A-4C05EECA13DA

I know that I should use the following query:

<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"/>

As PowerShell is my BFF when dealing with SharePoint, I wrote a short script to create this column :

# IT Joe – http://blog.jonathanroussel.com
# One Shot Script - Add a column to a list using a CAML query

[System.Reflection.Assembly]::LoadWithPartialName(”Microsoft.SharePoint”)

$siteurl = "http://moss:81/SB"
$mysite=new-object Microsoft.SharePoint.SPSite($siteurl)

if($mysite)
{
$web = $mysite.openweb()
if($web)
{
"WEB : " + $web.name + " / " + $web.title + " @ " + $web.url
$list =$web.lists["PhoneDirectories"]
if($list)
{
"List : " + $list.title
$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"/>')
}
$web.dispose()
}
$mysite.Dispose()
}

After running the script I open an item of the PhoneDirectories library and …. Voila:

image

As you can the Office column takes its value from:

image

One more remarks, if you try adding a new column “Office2” looking up the same list without the webid with the following CAML query :

<Field Type="Lookup" DisplayName="Office2" Required="FALSE" List="{45BE507B-DF8C-43BC-AF6A-4C05EECA13DA}" ShowField="Title" UnlimitedLengthInDocumentLibrary="FALSE" StaticName="Office2" Name="Office2"/>

You will see that this column works. I can imagine you thinking

“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!”

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...

Ok, spoiler alert, it won’t work. Seems like SharePoint needs at least one reference to the Web where the list to lookup is.

I don’t know if you will find It usefull but I hope you will like the trick.

Photo : Nelson's Column credit vgm8383 @Flickr

Wednesday, June 03, 2009

SharePoint Lookup Column and its limits

Lookup Pop by Tomas SharePoint comes with a very nice feature, the possibility to create columns (for lists, libraries metadata) based on lookup on other lists.

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.

If for example you have the following sites/subsites

image

Where SA, SB, SC, SD are SharePoint Sites (SPWebs) and SB includes a List L1.

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. : http://tonybierman.blogspot.com/2008/07/free-custom-cross-site-lookup-column.html).

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.

But it isn’t because I stumbled upon an interesting fact: there actually is a way to do that OOTB.

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.

You can now save DL1 as a library template and finally create a new document library DL2 in SC based on this template.

You get something like that:

image

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.

I don’t think it is usable in real life but it triggered something in me. 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 and guess what it works very well. I will give you more details very soon!

Edit: More Details in a newer post.

Photo : Lookup Pop credit Tomas @Flickr

Thursday, May 28, 2009

SharePoint Walktrough - Displaying List Items with their attachments Part 2/2

image

Recap

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.

I presented in Part 1 of this walkthrough how to create a DataView part consuming the Lists.asmx Web Service in SharePoint Designer to display the elements of a list. We are now going to display the attachments of these list elements.

To retrieve the attachments URLs we need to add an option to the Web Service Soap query, the “IncludeAttachmentUrls” option (details of the query options is available at http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spquery_properties.aspx). 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 http://blogs.msdn.com/sharepointdesigner/archive/2008/06/20/data-source-issues-and-workarounds.aspx for reference).

But there is a workaround!

4 – Modify the DataSource QueryOptions parameters

imageFirst you need to have access to the page source, so let’s switch SharePoint Designer to Split or Code view :

In the code, search for the line starting with: “SharePoint:SoapDataSource”. On the same line you shall see something like “ </listName></GetListItems></soap:Body>”.

image

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 :

<queryOptions><QueryOptions><IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls></QueryOptions></queryOptions>

So that the end of the soap request body looks like :

</listName><queryOptions><QueryOptions><IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls></QueryOptions></queryOptions></GetListItems></soap:Body>

Save the page and check the result in the design view :

image

The ows_attachments field now contains the attachments URLs or 0 for list items with no attachments using the following format :

;#http://moss/Lists/MyList/Attachments/1/Piece.txt;#http://moss/Lists/MyList/Attachments/1/Piece2.txt;#

We still need to make some nice links out of this field. Time to put on your XSL designer gear.

5 – Modify the XSL Presentation

We first create a XSL template to transform the string given by the Web Service into a nice series of picture. 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>”).

<xsl:template name="SplitAttachments">
<xsl:param name="str"/>
<xsl:choose>
<xsl:when test="contains($str,';#')">
<xsl:variable name="attachmentUrl" select="substring-before($str,';#')"/>
<xsl:if test="string-length($attachmentUrl) != 0">
<a href="{$attachmentUrl}"><img style="border:0px" src="/_layouts/images/attach.gif" alt='Open'/></a>
</xsl:if>
<xsl:call-template name="SplitAttachments">
<xsl:with-param name="str" select="substring-after($str,';#')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

This XSL template uses a recursive template to parse the attachments and generate corresponding links and pictures.

Now replace

<xsl:value-of select="@ows_Attachments"/>

By

<xsl:call-template name="SplitAttachments">
<xsl:with-param name="str" select="@ows_Attachments" />
</xsl:call-template>

And you should see this :

image

The paper clip icon you see are actually pointing to the attachments.

6 – Pimp up my Data View

At this point our Data View Web Part works ok but isn't as nice as you might want it to be.

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 MapToIcon template. If you give a file extension to this template, it will return the icon filename corresponding to this filetype.

Using the substring-after method to get the filetype we can imagine replacing :

/_layouts/images/attach.gif

By

/_layouts/images/{ddwrt:MapToIcon('',substring-after($attachmentUrl,'.'))}

imageNow save the file and check the result :

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.

7 – Conclusion

That’s it, you have got a functional Web Part to display your List.

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.

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.

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.

SharePoint Walktrough - Displaying List Items with their attachments Part 1/2

image 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 http://www.codeproject.com/KB/sharepoint/DataViewAttachments.aspx.

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 2nd April 2009 at http://www.microsoft.com/downloads/details.aspx?FamilyID=baa3ad86-bfc1-4bd4-9812-d9e710d44f42&displaylang=en ) and of course a MOSS or WSS instance.

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 part 2 of this walkthrough.

0 – Principle/Rationale

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.

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.

As a bonus this method will allows us to display the list items on a different SharePoint site or collection than the list itself.

1 – Create or Open a page

In SharePoint Designer after opening your site, either open an existing page or create a new one. I choose this last option:

image

Make some room for our content in the PlaceHolderMain zone of the page by creating a custom content.

image

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.

image

You should get something looking like that in the Design View:

image

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.

2 – Create a Web Service Data Source

imageThe page is now ready to host our Data View web part. Open the Data Source view by clicking Data View| Manage Data Sources.

imageChoose to connect to a web service:

In the Service Description Location enter: http://SP_SITE_URL/_vti_bin/lists.asmx, then click connect and choose the GetListItems operation:

image

imageDouble click on the listName parameter and enter the name or guid (between brackets {}) of your list.



imageValidate the Data Source Properties and check that it is working correctly by trying to see the data returned by this data source:

If a new panel opens with the list data, it means it’s working.

image

Troubleshooting:

If it isn’t working you will be presented with an enigmatic error message giving you absolutely no details:

image

This can be caused by numerous reasons you want to check:

  • The name or guid of the list is invalid
  • 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 (http://blogs.msdn.com/sharepointdesigner/archive/2008/06/20/data-source-issues-and-workarounds.aspx). We will modify those latter on.
  • 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.
Changing the Web Service authentication:

Open the Data Source properties

image

Open the login tab and choose basic authentication:

image

Save the details and try again to retrieve the data.

3 – Create the Data View Web Part

We now have a working Data Source, let’s create a web part to display it.

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).

image

You shall now see something like that in the design view.

image

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.

We will see in part 2 of this walkthrough how to solve this.

Saturday, April 25, 2009

Quick, Easy and Free WAN emulation with WANem

Fibre Channel cable By Herrolm @ Flickr

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.

We, of course, tried our different options in a mock up environment consisting of several virtual machines hosted on a single VMVare server instance.

As such, this set-up obviously lacked in representativeness of the actual environment. 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. 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.

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). 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 http://wanem.sourceforge.net.

As it is a live-cd, there is absolutely no installation to be done. 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.

WANEm Web Console in Advanced Mode

So, we have a very easy-to-use, functional software for free! Seems great! Too good to be true, wait, it’s not all; the documentation included is a delight. 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.

The WANEM Web console in basic mode

Anyway, they probably tought it wasn’t enough so they put a nice cherry at the top of the cake and created a VMWare server appliance with WANEm configured.

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).

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 http://wanem.sourceforge.net.

Fiber Channel photo courtesy of Herrolm @ Flickr

Friday, April 17, 2009

Sorting / Filtering SharePoint RSS feeds

Really, REALLY BIG RSS feed button by photopia / HiMY SYeD on flickr.com 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.

Et Voila !

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.

image

I first create two views filtering on the Etat column. One returns the pending elements, the other returns the finished elements.

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).

After making sure that RSS feeding is activated for my task list, I can go check the RSS feed at :

http://MyServer/_layouts/listfeed.aspx?List=a4a88bd0%2Ddf29%2D4f54%2Da924%2D195be47346ed

The results as displayed by IE7 looks like :

image

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=<VIEW_GUID>" to the URL and here is the result :

http://MyServer/_layouts/listfeed.aspx?List=a4a88bd0%2Ddf29%2D4f54%2Da924%2D195be47346ed&View=%7B9F3ACEAB%2D75DF%2D4C04%2D83C2%2D3A5733A6CA31%7D

image

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.

I wonder if this is documented anywhere as I stumbled upon this feature by pure chance ?

RSS picture credit Photopia on flickr

Sunday, April 05, 2009

Thinking of copying a locked SharePoint site collection ? Think twice !

clip_image002[7]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.

Eager readers will eagerly jump to the final conclusion.

Copying though stsadm backup/restore

Let’s try copying this site collection with the stsadm backup and restore commands. Both farms are MOSS RTM farms.

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.”) :

screenshot.1

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.

Conclusion : Not a good idea ! Might actually works using the trick I finally used, see below.

Copying using a SQL Server backup

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.

The restore wentsmoothly. I was starting to believe it was actually going to be easy!

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.

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.

clip_image004

Huh ? I tried validating the popup anyway and was presented with this screen:

clip_image006

It seemed just as if I had selected nothing, yet the adress bar contained the id of the content database :

clip_image008

Trying to unlock this site collection would produce kind of the same result.

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.

It was a relief to be able to see the details of the collection. Thou shan’t prevail over me SharePoint !

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.

clip_image010

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.

Conclusion : It works, but both farms have to be in the same AD domain

Final Conclusion

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.

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.

Monday, March 23, 2009

IIS 5 and 6 time-taken field

IIS_time_takenWhile 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.

Does the time-taken column in IIS 5 logs takes into account the network time ?

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:

According to :http://support.microsoft.com/kb/944884

Beginning in IIS 6.0, the time-taken field typically includes network time. 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.

According to :http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/676400bc-8969-4aa7-851a-9319490a9bbb.mspx?mfr=true

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. Time taken does not reflect time across the network. 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.

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.

That’s when I decided to contact the Microsoft Partner Support.

The definite answer they gave me for the time-taken field in IIS 5 logs is:

Since the calculation includes the time for the acknowledgement from the client, it may be skewed by any network latency issues.

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.

I hope it helps.


Edit : 29/06/2009

A reader (thank you Joe) pointed out to me that the http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/676400bc-8969-4aa7-851a-9319490a9bbb.mspx?mfr=true article as been updated with the following :

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:

  • The response size is less than or equal to 2 KB, and the response size is from memory.
  • TCP buffering is used.
So problem solved, but if anyone find the trace of the KB94483 mentionned, let me know because I can't !

Sunday, January 18, 2009

SharePoint : Search using « This Site » or “This List” scope returning no results

I met a problem with the Search scope on a MOSS 2007 farm the other day that I thought was worth blogging about.

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.

There are several reasons that can explains this problem according to this technet forum thread (http://social.technet.microsoft.com/Forums/en-US/sharepointsearch/thread/906045d8-8782-4c39-be1b-7632f7239019/#page:1), 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.

Our Alternate Access Mapping for this zone was defined as follow:

Private URL Zone Public URL
http://hostname Default http://hostname
http://intra.dnsname.com Intranet http://intra.dnsname.com

And we used http://intra.dnsname.com as the start address for the crawl.

We tried changing the content source start address from http://intra.dnsname.com to http://hostname, resetted the crawl content and launched a full crawl and that was it. The “This Site” and list scopes worked perfectly from then on.

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.

To solve that problem we changed the Alternate Acces Mapping configuration to:

Private URL Zone Public URL
http://hostname Default http://intra.dnsname.com
http://intra.dnsname.com Default http://intra.dnsname.com

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.

By the way, you might find this article about Alternate Access Mapping very useful: http://blogs.msdn.com/sharepoint/archive/2007/03/06/what-every-sharepoint-administrator-needs-to-know-about-alternate-access-mappings-part-1.aspx

Tuesday, January 06, 2009

Infinite looping the MOSS OOTB approval workflow

A few days ago, I noticed something weird with the Microsoft Office SharePoint Server out of the box workflow, most specifically with the workflow option to start when an item is modified.

I was trying to set up the Approval Workflow on a SharePoint List with content approval activated. I first set up the workflow to ask for approval when a new item is submitted to the list. It worked fine but we also needed to ask for approval when an item was updated (e.g. the writer made a mistake and notice it after the approver did his job, thus he modify the item that as a result needs to be approved a second time).

I fired up the workflow configuration page and checked the infamous “Start Workflow when an item is modified” in the start options.

From a french MOSS install

And from then everything went wrong. Whenever an approvers did his job by approving an item, the workflow would be launched again and a new approval task would be added to the workflow task list.

I tried tweaking the workflow, modifying the tasks list used … but nothing would do the trick, the workflow was stuck in an infinite loop whenever the “Start on item edit” was activated.

And that’s when it hit me, changing the approval status of an item seemed to be considered as a modification of the item itself.
I am still surprised by what I can’t help but see as a major flaw of SharePoint. I definitely don’t think that the approval status of an item is part of the item itself, it is only a SharePoint information about OUR piece of information (the item).

I also was surprised by how few people seems to react to this fact based on a few google search I made. Yet it seems other people faced the same problem (http://social.msdn.microsoft.com/Forums/en-US/sharepointworkflow/thread/62f5921d-9d02-4924-a61f-97ad169d1043/ and http://unitedsupplyco.sharepointsite.net/publicfacing/bensblog/Lists/Posts/Post.aspx?ID=34 ).

If you have any information about this subject, I would enjoy to know it.