Wednesday, April 23, 2014

SharePoint 2013 : Missing Suit links bar (Newsfeed, SkyDrive and Sites)

When we create a SharePoint farm, we may miss the top right navigation menu also known as “Suit links bar”

image

To make the navigation links available we need to follow the steps given below

1. Create user profile service application

image

2.Provide My Site host url in user profile service application

There are 2 places where you can provide the My Site host url

  • When provisioning the service application
  • “Setup My Sites” section

            image

            image

That will add relevant links to suit links bar

image

Sunday, April 20, 2014

Programmatically display all items in SharePoint document library as a flat list without folders

Let’s assume that we have a document library with a deep folder structure. Sometimes it’s very hard and time consuming to locate documents under those folders.

image

Is there a way to display all files as a flat list without folders? It’s very simple, we only need to do some modifications to the view

image

If we have to automate the behavior, we can use either C# or PowerShell to do the needful. In both cases we need to update SPView.Scope property.

C# 

  1. var viewCollection = newDocLib.Views;
  2. const string viewName = "File List";
  3. var viewFields = new StringCollection
  4.          { "Type", "LinkFilename", "Modified", "Editor" };
  5. var filesOnlyView = viewCollection.Add(viewName, viewFields, string.Empty, 5, true, false);
  6. filesOnlyView.Scope = SPViewScope.Recursive;
  7. filesOnlyView.Update();
  8. newDocLib.Update();

PowerShell

Following script will create the view for all document libraries in all site collections within a specific web application

  1. Get-SPSite -WebApplication "http://sp13:8080" -limit All | ForEach-Object {  
  2. foreach ($w in $_.AllWebs){
  3. foreach($docLib in $w.Lists | where {$_.BaseTemplate -eq "DocumentLibrary"})
  4.   {
  5.     #create list view
  6.     $viewCollection = $docLib.Views
  7.     $viewName = "File List"
  8.     $fields = $docLib.Views["All Documents"].ViewFields.ToStringCollection()
  9.     $itemOnlyView = $docLib.Views.Add($viewName, $fields,"", 30, $True, $False)
  10.     $itemOnlyView.Scope = "Recursive"
  11.     $itemOnlyView.Update()
  12.     $docLib.Update()        
  13.   }
  14. }
  15. }

This will create a new view called “File List” which displays all files in the library without folders

image

Thursday, April 17, 2014

SharePoint : Open documents in browser for Office Web Apps using PowerShell

Recently we configured Office Web Apps in a SharePoint 2013 farm. But it didn’t work for most of the site collections as office documents were downloading instead of opening in the browser.

image

This is because it is set to open documents in client application. You can see it in the library settings in each document library.

image

If we change the setting back to “Open in the browser”, documents will open in Office Web Apps as expected. Is there any easier way to do the change for every site instead of change it at library level?

Luckily there is an easier way. The Open in client application behavior is enabled by a site collection feature.

image

If we deactivate the feature the setting will revert back to “Open in the browser” option.

We used following PowerShell to deactivate above feature for all site collections in the farm

  1. $clientFeature = "8A4B8DE2-6FD8-41e9-923C-C7C3C00F8295"
  2.  
  3. Get-SPSite -WebApplication "http://525256-wfe2013:5003/" -limit ALL | ForEach-Object {
  4. if ($_.Features[$clientFeature] -ne $null) {
  5.    Disable-SPFeature -Identity $clientFeature -url $_.URL -Confirm:$false
  6. }
  7. }

That’s all we have to do

image

Saturday, April 12, 2014

PowerShell : count occurrences of specific character in a string

Recently I wanted to count the occurrences of specific character in a string.

As an example, let’s say we want to count number of  ‘/’ characters in a given url . Following is a sample PowerShell to get the result.

  1. $url = "http://sp13/sites/1/2/3"
  2. $charCount = ($url.ToCharArray() | Where-Object {$_ -eq '/'} | Measure-Object).Count
  3. Write-Host $charCount

Tuesday, April 8, 2014

Extend SharePoint Host-named site collection using different url

In SharePoint there are two types of site collections namely Host-Named sites and Path based sites. Although path based site collections (e.g.: http://sp13/sites/hr) were the commonly used practice in previous versions of SharePoint, host-named site collections (e.g.: http://hr.sp13) are the preferred method in SharePoint 2013.

One advantage of host-named site collections is the ability to map multiple urls to such site collections. It is somewhat similar to extending a web application to a different zone. But in this case we can extend only a site collection to have multiple urls (up to 5).

Let’s take following scenario. I have a web application with 3 site collections. I need to extend only the HR site to our partners through a different url. How can we do that ?

image
If we used the web application extend approach, all site collections will be available in extended url although they are not required. So the best practice would be to create those site collections as host-named site collections and map another url.

Following are the steps to create a host-named site collection and map to different urls

1. Create host-named site collection

We can use following PowerShell statement to create the site collection. “HostHeaderWebApplication” switch allows us to create host-named site instead of a path based site

  1. New-SPSite 'http://hr.kiwi.com' -HostHeaderWebApplication 'http://sp13/’ -Name 'HR' -Description 'Portal Site' -OwnerAlias 'dev\spadmin' -language 1033 -Template 'STS#0'

2. Map urls to host-named site collection

To map new urls to the site we will use Set-SPSiteUrl command

  1. Set-SPSiteUrl -Identity http://hr.kiwi.com -Url https://hr.kiwiportal.com

If we want to position the new url at a different zone, we can use optional “–Zone” switch. Otherwise the url will be created at the Default zone.

  1. Set-SPSiteUrl -Identity http://hr.kiwi.com -Url https://hr.kiwiportal.com -Zone Internet

According to the best practice, a SharePoint farm should have only one web application and one zone. Limiting to one web application and one zone has some advantages

  • One application pool, which preserves resources in most cases
  • Keeping one zone in a web application helps us to easily deploy apps. Otherwise if we have multiple zones and Alternate Access Mappings (AAMs) it’s not possible to deploy SharePoint apps.

Because of that it is advisable to create external urls in the Default zone as well

If our SharePoint farm is equipped with RTM version we will encounter following error while adding multiple urls to same zone

image

Unfortunately to avoid the error we have to upgrade SharePoint into latest version.

Wednesday, April 2, 2014

Create SharePoint site using provisioning provider

In most cases, when we provision a site collection, we expect some customizations also to be created along with that site collection. Customizations can be branding, web parts, event receivers, etc..

There are several techniques to provision customized sites in SharePoint. Mostly important techniques are

  • Site definitions
  • Web templates
  • Provisioning Providers

Let’s assume we need to create a site collection programmatically with few web parts positioned in the home page. What do we normally do ? There are 2 approaches

The wrong way

We may use following steps to create the site

  1. Create a web service or console application to create site collection using built in template
  2. Add each web part to the page sequentially
  1. var spWebApp = SPWebApplication.Lookup(new Uri(appUrl));
  2. using (var site = spWebApp.Sites.Add
  3.     (siteUrl, siteTitle, "", 1033, "STS#0", login, userName, ""))
  4. {
  5.     //Add webpart 1
  6.     //Add webpart 2
  7. }

What is the problem with this approach?

The issue is that the Sites.Add method executes asynchronously. Hence we might be trying to add web parts or other customizations to a site which is still being provisioned.

The correct way

The best practice is to provision such site collection using a provisioning provider. Following are the steps in creating a site using provisioning provider.

     1. Create custom behavior using new class extending SPWebProvisioningProvider

  1. public override void Provision(SPWebProvisioningProperties props)
  2. {
  3.   var web = (SPWeb)props.Web;
  4.   web.ApplyWebTemplate("ContosoSites#1");
  5.   //Change the description to demonstrate
  6.   web.Description = "created by provisioning provider";
  7.  
  8.   //Add webpart 1
  9.   //Add webpart 2
  10.   web.Update();
  11. }
 

    2. Create site definition

Site definition contain 2 files, namely “Onet.xml” and “webTemp.xml”. Following is a sample “Onet.xml” file

image

   3. Specify ProvisionAssembly and ProvisionClass elements in web template file

  1. <Templates xmlns:ows="Microsoft SharePoint">
  2.   <Template Name="ContosoSites" ID="10002">    
  3.     <Configuration ID="0"
  4.                    Title="Contoso HR Site"
  5.                    Hidden="FALSE"
  6.                    ImageUrl="/_layouts/images/CPVW.gif"
  7.                    ProvisionAssembly="STSTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ec660d77d5010c78"
  8.                    ProvisionClass="STSTest.ContosoProvisioningProvider"
  9.                    Description="Contoso HR Site"
  10.                    DisplayCategory="Contoso Sites">
  11.     </Configuration>
  12.     <Configuration ID="1"
  13.                    Title="Contoso HR Site"
  14.                    Hidden="True"
  15.                    ImageUrl="/_layouts/images/CPVW.gif"
  16.                    Description="Contoso HR Site"
  17.                    DisplayCategory="Contoso Sites">
  18.     </Configuration>
  19.   </Template>
  20. </Templates>

You may notice that, we’ve created two configuration elements for same “Contoso HR Site”. This is to avoid circular reference when applying the template from the provisioning provider.

In addition to the configuration which attaches the provisioning provider we will create a hidden configuration as well. From the provisioning provider we will apply the hidden configuration. By doing that we can avoid the circular reference

   4. Deploy the solution

   5. Create new site

         image