Thursday, January 31, 2013

How to debug the SharePoint People Picker Problems

In complex environments you often have to adapt the SharePoint people picker settings for performance or other business needs reason. In this post I'll show two common problems.

Example 1: The people picker takes too long to find a user.

The szenario is that you search for a user and you wait 1 or longer minute before the user is displayed in the people picker.

One reason for that is often that the whole AD with all subtrees and trusted ADs is searched. This can be easily fixed by setting a filter to the people picker (like shown here).

Another reason can be that there are multiple Domain Controllers which the SharePoint Server tries to contact. There will be a delay if some of them are sitting behind a firewall like in a DMZ. This can be fixed by opening the ports to the DCs or by modifiying the host file, by pointing th IP of the DCs behind the firewall to  DCs in front.

Example 2: Your company consists of multiple branches with their own AD

You can tell the peoplepicker to search multiple domains. If you have a 2-way trusted domains, this problem can be easily fixed with a stsadm command:

 stsadm -o setproperty -pn peoplepicker-searchadforests -pv "domain:germany.mydomain.com;domain:turkey.mydomain.com" -url http://sharepoint  

Replace the domain names and the web application url for your needs. 

How to Debug

We take the example 2. What if you set the stsadm command in the second example but you can't find any user from the other domain ?

I use first a powershell script to check if I can contact the new DC. You have to know a little bit how ldap queries are working to understand the script.

Just adapt the DirectoryEntry setting and enter the login in DisplayUser( login ) at the bottom.

 <#   
   Display user information from AD  
   @author: Ihsan Baris Bikmaz  
 #>  
 clear  
 function DisplayUser($cn) {    
   $strFilter = "(&(objectClass=User)(cn=$cn))"  
   $objDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://OU=Users,DC=turkey,DC=mydomain,DC=com")  
   $ds = New-Object System.DirectoryServices.DirectorySearcher  
   $ds.SearchRoot = $objDomain  
   $ds.PageSize = 1000  
   $ds.PropertiesToLoad.Add("displayName")  
   $ds.PropertiesToLoad.Add("co")  
   $ds.Filter = $strFilter  
   $ds.SearchScope = "Subtree"  
   $retArray = @()    
   Write-Host " >> Searching for User with cn: " $cn  
   $ds.Findall() | Sort Path | ForEach-Object {  
      $dname = $_.Properties.Item("displayName");   
      $element = New-Object System.Object  
      $element | Add-Member -type NoteProperty -name CN -value $cn  
      $element | Add-Member -type NoteProperty -name Name -value $dname  
      $retArray += $element  
   }    
   $retArray  
 }  
 $myArray = @()    
 $myArray += DisplayUser("abikes")  
 $myArray  


When this script works without any problems. I go further by digging in to the ldap traffic between the SharePoint Server and the DC.

The tool I use for monitoring the traffic is WireShark . Install WireShark on your frontend server. Start it. Select the adapter to connect and start monitoring the network traffic.

Start WireShark

You'll see lots of traffic. Now enter "ldap" in the filterbox and click on apply to only see ldap traffic.

Apply LDAP Filter

The next step is to create ldap traffic. Therefore open any SharePoint Site. Just go to the site actions menu and select Site Permissions. Try to search a user in the new AD. As an example I search a user with the loginname "anncle".

You will see now some traffic in the WireShark. Click on stop monitoring.

Stop monitoring

Click on Edit Menu and then on "Find Packet". Give the loginname you searched for into the search box.

Find Packet

Now you can see the ldap query, the time which the DC's need to respond and which DCs are contacted. With all that information it is easier to debug and find out the real problem.

In my case I check the query which the WFE send to the DC.

Ldap Query

With right click you can copy the query and you can try and modify it with Tools like LdapAdmin.

In my case, by inspecting  the ldap query  I found out that I had a filter which I set prior to improve the performance. By removing the filter from the sitecollection everything worked fine.



Wednesday, January 16, 2013

Delete a SharePoint 2010 Site Collection


When you delete a site collection in SharePoint 2010 from the Web UI it is not immediately deleted. The site is inserted into a queue of "To be deleted" sites. A timer job (Name:Gradual Site Delete) then deletes the sites at some point. This is called "GRADUAL DELETION". This is recommended when you delete large sites to use less system load.

Sometimes this can cause errors when you want to create a site collection with the same url immediately after you deleted one. Then you have to wait until the site is really deleted by the timer job or use PowerShell to speed up the process.

Helpful PowerShell Commands

1.) You can list the sites in the deletion queue with PowerShell:

 Get-SPDeletedSite  



2.) To delete a site in the queue you can also use PowerShell:

 Remove-SPDeletedSite -Identity 1f11a7e8-4e89-48ref-af8a-ad805a505753 

(Identity is the SiteId)

3.) To restore a site collection in the queue use:

 Restore-SPDeletedSite -Identity 1f11a7e8-4e89-48ref-af8a-ad805a505753 

4.)If you want to delete a site collection right off without throwing it into the deletion queue use PowerShell with Gradualdelete = false option:

Remove-SPSite –Identity "http://sitename" –GradualDelete:$False


Resources

Tuesday, January 8, 2013

SharePoint Web Folders - Create a Desktop Shortcut to a SharePoint library on Windows XP with and without SSL

Shortcuts with HTTP Connections

If you have a http connection to a SharePoint site within your network you can create easily a shortcut on your desktop.

First copy therefore the url of your library until /Forms/xxx . Example: If your URL is like

  • "http://sharepoint/sites/projectx/team%20documents/Forms/AllItems.aspx

copy the part

  • "http://sharepoint/sites/projectx/team%20documents


Right click on your desktop and select "Shortcut".  Paste the link into the the textbox without http: and revert all slashes to backslashes. Also decode all urlencodings here. The final path should look like that: "\\sharepoint\sites\projectx\team documents"


An easy way to get this path is by clicking the explorer view in the SharePoint library.



On Windows you can simply enter the WebDav address in the file explorer to open a WebDAV connection to a SharePoint library.




Shortcuts with SLL Connections

But this only works with the standard http protocol on Windows XP. If you are using https you can only create a network resource under My Network Places. This network resources are called Web Folders.

You can create a Web Folder for SharePoint in two ways. The complicated and the easy way

Complicated Way

  1. Open the File Explorer and click on Network
  2. Click on Folders in the menu


  3. Now you can see the "Add network resource" link. Click on it.
  4. Follow the steps.
  5. Add your URL to the library

  6. Finish
Now you'll see a link to your Web Folder within the network.

Easy Way 

This network resource to the web folder is automatically created when you open a SharePoint library with the exporer view.

Explorer View in the library

Create a ShortCut on your Desktop

To create a shortcut on your Desktop which opens the web folder you have to do the following three steps.


  1. Open the web folder within the network. Just click on it.

  2. Add the web folder to the your favorites in the file explorer (not internet explorer).

  3. Now you have the shortcut in the menu. Right click on it and select "Send to" => "Desktop"

You can also right click on the web folder and select "Send to" but this didn't work for me, so I found this way.

Create a ssl shortcut on Windows 7

  1. Map to a network drive with the https url
  2. Open file explorer and enter the UNC Path of the Web Adress in the following format:
    "\\yoursharepointsite@SSL\DavWWWRoot\sites\yoursite\yourlist

Friday, January 4, 2013

Getting Web Url with SharePoint 2010 JavaScript API

There are multiple ways to get the current web url in SharePoint 2010 with the JavaScript API. I'll show you some different ways to get the url.


1.Way: Use global variable

There is a global variable "L_Menu_BaseUrl" which you can use to get the relative url. To get the full url use :

location.protocol + "//" + location.host + L_Menu_BaseUrl
 var url = location.protocol + "//" + location.host + L_Menu_BaseUrl  

The problem with this solution is that L_Menu_BaseUrl is a global variable and can be overwritten by other scripts or by other variables with the same name.


2.Way: Read attribute value

Read the href value of the top breadcrumb navigation node. There is a breadcrumb in every SharePoint site. You can just read the href attribute of the link, which always points to the web url.

 document.getElementById("ctl00_PlaceHolderSiteName_onetidProjectPropertyTitle").href  

The problem with this solution is, that when you habe other placeholder names (custom masterpage) or a site without a global breadcrumb the value will be empty or undefined.


3.Way: Use ctx variable within a list.

If you are creating a ribbon element for a list you can also use the ctx variable. This variable is created where a list webpart exists. To get the url of the web use the following:

 var webUrl = ctx.HttpRoot;  


The same problem as the first way. A global variable can be overwritten. Especially tctx is used very often used as variable name in other scripts and if a function doesn't use the var before the ctx variable, the variable is easily overwritten.


4.Way: Within the ASPX Site

If you are writing inline JavaScript Code directly within an aspx Site you can use shorcuts

 var url = "<%=SPContext.Current.Web.Url %>"  

The problem with this solution is that you can't use shortcuts js files.


5. Way: JS Client API

The safest way is to use the client javascript API, but it is also the most complicated way.
You have to understand how request are sent asynchronously and how they are handled with callbacks.

 ExecuteOrDelayUntilScriptLoaded(getWebProperties, "sp.js");    

 // Define namespace  
 NS = typeof NS == "undefined" ? {} : NS;  

 // Placeholder for web title  
 NS.WebURL = "";  

 NS.GetWebUrl = function(callback) {   
   var ctx = new SP.ClientContext.get_current();   
   var web = ctx.get_web();   
   ctx.load(web, 'Title', 'ServerRelativeUrl');   
   ctx.executeQueryAsync(  
     function() {//success
       NS.WebURL = web.get_serverRelativeUrl();  
       callback()  
     },   
     function() {//error
       NS.WebURL = ""  
       callback()  
     }  
   );   
 }    
 NS.AlertUrl = function() {  
   alert( "The relative url of the web is: " + NS.WebURL );  
 }

 // start call
 NS.GetWebUrl( NS.AlertUrl );  


In this example I first create a namespace NS. This is used to bypass method name collisions. Then I create a variable WebURL within the namespace to hold the web url.

The method NS.GetWebUrl ist the place where a request is send to the web service to get the title of the site. The request is sent async therefore we have to callback functions one for success and one for the error.
The method takes a callback as an argument, which is called after the reponse cames back from the server.

The AlertTitle funtion alerts the title of the site.