Monday, January 16, 2012

Office Communicator integration in a custom webpart for SharePoint 2010

With SharePoint 2010's new social capabilities, I see this integration as being a must-have for any webpart or other custom interface that refers to people.

How does SharePoint do it?
Whenever a person's name is mentioned in the standard SharePoint UI, if the user has Office Communicator installed, the name will be shown with the Office Communicator 'pawn'. The pawn shows the user's status and gives them access to the pop-up menu to see more details.
Depending on which version of Office the user has installed, the experience will vary, however it will be the same experience as seen in Outlook. In Office 2010 it is a square icon with a richer drop-menu, in 2007 it is round.






In addition to the pawn, the user's name will be a hyperlink to their profile page. This will vary depending on whether the user is in the main 'User Profile Service Application' (or 'profile database' for old-school terminology) or not. If the user does have a profile then the hyperlink will redirect to the user's main profile page under My Site. If the user does not have a profile, the hyperlink will redirect to the SharePoint Foundation 'User Information' page. All users in a site have a 'User Information' page, if they also have a User Profile the settings from the profile are synchronised down to the User Information page on a scheduled basis (by a timer job).

The key piece of information to make the presence work is the user's SIP Address which is basically their IM address (This is not always the same as email address). When a users is either added to a site in SharePoint or has their profile imported, the SIP Address will be drawn from Active Directory which is where OCS stores it and placed into the SIP address field in either the user's profile which will in turn synchronise down to the site's local 'User Information' page.

How does the pawn work in terms of HTML?

The pawn is basically an IMG element which has "IMNRC('[user's SIP Address]')" for the onload function. This will user client-side script that is part of Office to load the presence pawn on the page.
The hyperlink on the user's name is just a simple A element which redirects to "/_layouts/userdisp.aspx?ID=[User's local user information list item ID]". This userdisp.aspx page will then redirect to the user's main profile page if they have a profile, otherwise it will display the basic information that the user information list item stores.

How to get the SIP Address?

Hopefully you'll have spotted by now that the presence pawn relies on the user's SIP Address. To get the SIP address you need to get the user's User Information list item from the local site's (SPWeb to be precise) SiteUserInfoList which is basically a hiddenSPList that is in every web.
There is a handy property to get you to this list called 'SPWeb.SiteUserInfoList'. This will give you an SPList object which represents the User Information list. From here you just need to find the item that represents the user you wish to display. The best way to do this is via their ID (the ID of the list item) by calling SPWeb.SiteUserInfoList.GetItemById([int User's ID]), however you can also use a variety of other methods which use SPQuery or match a specific field to a value.
In most scenarios, you may be getting the user information from a SPFieldUserValueCollection which is basically the field type that is used for 'Person' fields. If this is the case you can use SPFieldUserValue.LookupId to get the ID of the user's User Information list item.

Putting it all together

This code sample is a method that accepts an SPFieldUserValueCollection and SPSite as inputs and returns back the HTML for displaying each entry in the SPFieldUserValueCollection with the presence pawn and link to their profile. This will be presented exactly as SharePoint presents it by default. This could be extended to use ALT tags in the IMG and A elements.
I then simply add the HTML to an HtmlWriter or in my case a TableCell.Text property to display it on screen. I've take a few extra steps here by adding ID and alt tags and trying to make the code readable, but I'm sure you get the idea:

Friday, January 6, 2012

What really happens in the background when a user performs a SharePoint search

Below is the diagram that gives you a pictorial vision of the high level communication that happens between IIS, MSSearch.exe, the Search DB and the Full-Text Index.




















Below is a breakdown of the 6 different stages.

Stage 1:

First thing that you need is the search query. The WebPart or the Web Service helps build up a search query. This search query is then passed to the Query Object Model (OM) via the WebPart or the Web Service.

This step happens between the client machine that submits the query and the web front end. Network traffic would show the following GET and the response:

Request:

GET /searchcenter/Pages/Results.aspx?k=sharepoint&s=All%20Sites HTTP/1.1Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*Accept-Language: en-usUA-CPU: x86Accept-Encoding: gzip, deflateUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)Host: wfeConnection: Keep-AliveAuthorization: NTLM TlRMTVNTUAADAAAAGAAYAHQAAAAYABgAjAAAAA4ADgBIAAAAGgAaAFYAAAAEAAQAcAAA
AAAAAACkAAAABYKIogUCzg4AAAAPQwBPAE4AVABPAFMATwBBAGQAbQBpAG4AaQBzAHQAc
gBhAHQAbwByAEQAQwApEBdASjCmUQAAAAAAAAAAAAAAAAAAAABd0mXyd+vSlujhEVc5rpV dPtQYe1WTXa0=Cookie: WSS_KeepSessionAuthenticated=80; MSOWebPartPage_AnonymousAccessCookie=80

Note (Highlight): In the above GET request ‘k’=keyword used and‘s’=scope

Response:

HTTP/1.1 200 OKCache-Control: private, max-age=0Content-Length: 76654Content-Type: text/html; charset=utf-8Expires: Tue, 08 Dec 2009 22:33:34 GMTLast-Modified: Wed, 23 Dec 2009 22:33:34 GMTServer: Microsoft-IIS/6.0X-Powered-By: ASP.NETMicrosoftSharePointTeamServices: 12.0.0.6318X-AspNet-Version: 2.0.50727Set-Cookie: WSS_KeepSessionAuthenticated=80; path=/Set-Cookie: MSOWebPartPage_AnonymousAccessCookie=80; expires=Wed, 23-Dec-2009 23:03:34 GMT; path=/Set-Cookie: http%3A%2F%2Fwfe%2FSearchCenter%2FDiscovery=WorkspaceSiteName=U2VhcmNo&WorkspaceSiteUrl=aHR0cDovL3dmZS9TZ
WFyY2hDZW50ZXI=&WorkspaceSiteTime=MjAwOS0xMi0yM1QyMjozMzozNQ==; expires=Fri, 22-Jan-2010 22:33:35 GMT; path=/_vti_bin/Discovery.asmxDate: Wed, 23 Dec 2009 22:33:34 GMT



Stage 2:

The query Object Model then in turn calls the Query Processor. The role of the Query Processor is to join results from the Full-Text Index with the SearchDB.

On SQL the two databases that are queried are:


  • SSP database.
  • SSP Search database.

On the SSP database proc_MSS_GetKeywordInformation is run to get the keywords for displaying on the site if Office SharePoint Search is being used.
On the search database the proc_MSSGetMultipleResults is run to get the properties from MSSDocProps table. Both these stored procedures and more details about them can be viewed via a SQL trace.

Stage 3:

The Query processor then opens a Query Pipe to the query machine. The link between the Web Front End and Query server is a query pipe only provided by MSSearch.exe. When the Query pipe network traffic is examined, it is revealed to be SMB traffic. Network Monitor 3 will identify this traffic as being the CIS protocol

A high level overview of what we can see via a Network Monitor capture is below.

The initial communication from the WFE to the Query Server occurs via one of the random (1024 to ~65000) WFE ports. This is done to Query ports 139 and 445 and finally establishing the connection through SMB.

In the network capture you will also notice a 'Tree Connect AndX Request' for path \\QueryServer\IPC$ from WFE's random port to the Query machine's port 445. Port 139 is used as the end point mapper.

Once the Tree is created, the path is changed to \OSearch in order to be able to query the flat files inside the Query server's file system.
Note however that at this point the default 'searchindexpropagation' share which is used while propagating index from index server to the query server is not used to retrieve the query responses.

Stage 4:

The indexer plug-in (refer diagram) on the query machine retrieves the results from the index. The Indexer Plug-in is the only part of Query that will access the Full-Text Index. We will get into more details about this in the following blogs of the same series. .

Stage 5:

Now let’s get into the part where the results are returned. The results come back from the Full-Text Index as DocIds. This task occurs based on the data that the web front end receives back from the Query and the SQL servers.

Stage 6:

The end result is then the function of the query processor (refer diagram above). The Query processor joins results from the Search DB and full text index. It takes the DocIds and does the join to the SearchDB to access the document properties (Title, Display URL, doc format, size, etc). This task occurs based on the data that the web front end receives back from the Query and the SQL servers.