Subscribe: SharePoint SharePoint SharePoint

Sunday, February 9, 2014

10 responsibilities and duties of a SharePoint Administrator

I was working on SharePoint project when my client asked me "What are the duties and responsibilities of a SharePoint Admin ? ". She actually liked SharePoint and wanted to try for getting a job there. Eventually i mailed her all details about a SharePoint Admin, so thought of sharing it with you all !
Powershell


SharePoint Administrator is a person who is solely responsible for configuration and maintenance of a SharePoint Server or a Farm. Promoting user adoption, developing and implementing a governance plan, implementing compliance and discovery, negotiating SLAs, enforcing ownership of applications and sites with stakeholders, collaborating with developers and testing backups is an essential part of a SharePoint Admin's duty.

Roles,Responsibilities and Duties of a SharePoint Admin:

1. Installing, configuring, maintaining, upgrading and managing a SharePoint Server or a Farm.
2. Configuring all service applications like Search, Metadata, UserProfile Synchronization etc.
3. Creation of a Content DB and maintaining it. It involves maintenance of various logging databases in SQL Server. Compressing of logging Databases is also done by SharePoint admins since they grow in size considerably.
4. Assignment of proper permission levels for all users of the site as well as configuring anonymous access if required .
5. Configuring timer jobs depending on business requirements. Timer jobs are very important in SharePoint. One of the timer job is to backup the sites everyday. This is very important as it helps to restore the site to its previous version if any error occurs.
6. Knowledge of powershell is very important for a SharePoint Admin. Clients usually prefer a person who can configure the whole system using powershell since it's much faster than UI. In one of my projects, the whole farm configuration was based on a powershell script which almost took 45-50 minutes to execute. It would have taken hours if the same thing was done using UI.
7. Training and supporting the business users in their day to day involvement in SharePoint sites. For instance uploading a document, starting an approval workflow etc.
8. Solid understanding of IIS, Active Directory and Mail Configuration.
9. Configuration of Business Connectivity Services for connecting to a SQL database or a WCF service.
10. Strong understanding of what can be done using OOB features in SharePoint.

Saturday, February 8, 2014

Content Query Web Part Empty Data Text

In one of the sharepoint projects that i was working on , there was a content query web part which displayed articles from an Articles subsite. There was a filter on the queried data which only showed data as per a metadata term. Now this web part was present in every other subsite. So in some of the sites it showed data while in others since there was not data to be shown, an empty web part was rendered.

SharePoint 2010

Now my client wanted to show a custom  message to the user in the CQWP like :
"No Items are currently available. Please check again soon."

So in order to do this i made some changes to the "ContentQueryMain.xsl" file in :
"\Style Library\XSL Style Sheets\ContentQueryMain.xsl"

There is one template in this file which indicates an "Empty" data. It's called "OuterTemplate.Empty".
I replaced that template with my own code and it worked perfectly fine.So anytime if there was no data to be shown in the CQWP, a custom message was displayed.

The code which i used for the  "OuterTemplate.Empty" template is as follows:
 <xsl:template name="OuterTemplate.Empty">  
     <xsl:param name="EditMode" />  
     <div id="linkitem" class="item link-item">  
       No Items are currently available. Please check again soon.  
     </div>  
       <xsl:if test="$EditMode = 'True' and string-length($cbq_errortext) = 0">  
         <div class="wp-content description">  
           <xsl:value-of disable-output-escaping="yes" select="$cbq_viewemptytext" />  
         </div>  
       </xsl:if>  
   </xsl:template>  

Thursday, February 6, 2014

How to provision Managed Metadata columns in SharePoint

Once i came across a requirement from my client involving creating of a branding package for his SharePoint site in visual studio. Now in this particular package i had to add custom master pages, page layouts, css files, js files etc.

For each page layout i had to create separate content types with some site columns. These site columns too were created in visual studio.

Now one of these site columns was a metadata column i.e. a "Taxonomy Field". I did create the whole package but when i deployed it, i found that metadata columns were not connected to Term Store.

Powershell


Since this was the first time i had worked on this kind of project so was not aware that MMS Term store needs to be connected to a Taxonomy column. I could have done the same using UI, but my client wanted it to be automated.

I came across two approaches to do so. So thought of sharing those:

1. Elements.xml : In elements.xml file of the site column, we can easily specify the termsetid so that the column can connect to term set:

*Here ShowField="Term1033" is necessary field property.
NOTE: You can find the SSPID, GroupId and TermSetID from Term Store Management link in Site Settings.
 <?xml version="1.0" encoding="utf-8"?>  
 <Elements xmlns="http://schemas.microsoft.com/sharepoint/">  
  <Field  
     ID="{99e8cfdc-3edb-4d0e-b22e-0bde0cfe8dfd}"  
     Type="TaxonomyFieldType"  
      DisplayName="LOB"  
      ShowField="Term1033"  
      EnforceUniqueValues="FALSE"  
      Group="Custom"  
      StaticName="LOB"  
      Name="LOB">  
   <Customization>  
    <ArrayOfProperty>  
     <Property>  
      <Name>SspId</Name>  
      <Value  
      xmlns:q1="http://www.w3.org/2001/XMLSchema"  
      p4:type="q4:string"  
      xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">  
       9a5c42de-abb1-489e-87df-c68c2a30c9fc  
      </Value>  
     </Property>  
     <Property>  
      <Name>GroupId</Name>  
      <Value  
      xmlns:q2="http://www.w3.org/2001/XMLSchema"  
      p4:type="q2:string"  
      xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">  
       d86f5d20-8878-4b0d-8ef2-b7a24272e5f3  
      </Value>  
     </Property>  
     <Property>  
      <Name>TermSetId</Name>  
      <Value  
      xmlns:q2="http://www.w3.org/2001/XMLSchema"  
      p4:type="q2:string"  
      xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">  
       3ff7c119-8ad1-4676-b4f0-6d5618840527  
      </Value>  
     </Property>  
     <Property>  
      <Name>AnchorId</Name>  
      <Value  
      xmlns:q3="http://www.w3.org/2001/XMLSchema"  
      p4:type="q3:string"  
      xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">  
       00000000-0000-0000-0000-000000000000  
      </Value>  
     </Property>  
    </ArrayOfProperty>  
   </Customization>  
  </Field>  
 </Elements>  

2. Powershell : If we have already deployed the solution without connecting the columns to term store and we don't not want to change anything in the package. Then we can utilize powershell to connect to the Term Store :

 $centralAdmin = Get-SPWebApplication -IncludeCentralAdministration | Where {$_.IsAdministrationWebApplication} | Get-SPSite  
 $session = new-object Microsoft.SharePoint.Taxonomy.TaxonomySession($centralAdmin)  
 $serviceApp = Get-SPServiceApplication | Where {$_.TypeName -like "*Metadata*"}  
 $termStore = $session.TermStores[$serviceApp.Name]  
 $termSet = $termStore.Groups["Department"].TermSets["IT"]  
 $site = Get-SPSite http://myWebApp/sites/mySite  
 $web = $site.RootWeb  
 $taxonomyField = $web.Fields | Where { $_.Id -eq "99e8cfdc-3edb-4d0e-b22e-0bde0cfe8dfd" }  
 $taxonomyField.SspId = $termSet.TermStore.Id  
 $taxonomyField.TermSetId = $termSet.Id  
 $taxonomyField.AllowMultipleValues = $false  
 $taxonomyField.Update();  

Make sure you specify the GUID of the site column correctly, so that it can connect to the term store.

After following any of the above approaches you can see that the column is connected to Term Store.:

Powershell

Wednesday, February 5, 2014

"Sign in as Different User" menu option is missing in SharePoint 2013

In SharePoint 2013 you might have noticed that "Sign in as different User" menu option has been removed. Microsoft has decided to discontinue this option owing to a variety of different reasons. Though to SharePoint Admins and Approvers it might seem to be a big issue.

Since in SharePoint 2010, this menu option did offer a lot of help in checking the permission levels for various groups in SharePoint sites, same thing does not hold true for SharePoint 2013.



The reasons which might have caused Microsoft to remove this option may be summarized as below:

1. There are a lot of caching problems. The cache for one user can contradict with the other one.
2. Page content might show data and content from previous logged in users.

Now there are a number of ways to use this option :

1. In the browser just  append this link to your site url : /_layouts/closeConnection.aspx?loginasanotheruser=true

2. Another permanent solution is to make changes to the welcome.ascx user control which is located at "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\CONTROLTEMPLATES\welcome.ascx"

Add the following code in it before this tag --> "SharePoint:MenuItemTemplate tag with id ID_RequestAccess":

 <SharePoint:MenuItemTemplate runat="server" ID="ID_LoginAsDifferentUser"  
 Text="<%$Resources:wss,personalactions_loginasdifferentuser%>"   
 Description="<%$Resources:wss,personalactions_loginasdifferentuserdescription%>"   
 MenuGroupId="100"  Sequence="100"  UseShortId="true"  />  

After doing this do an IISREST and you should be able to see the required option :




Tuesday, February 4, 2014

Check in and approve all publishing pages using PowerShell in SharePoint

We have a SharePoint 2013 farm setup for our company Intranet. There are huge number of sites in the intranet. Each site is maintained by a separate group. Now the people who maintain those sites are non-technical people.

Since all the sites are publishing sites, so the pages need to be published everytime they are edited. I have repeatedly sent mails to all groups stating that this procedure has to followed everytime they make changes.

But alas! , everyday my mailbox is clogged with requests reporting that "changes are not being reflected to site visitors". Instead of sending separate mails to each of them, i made a powershell script to publish all their pages together.

Note: The image is just for reference. Its not actual screenshot of the below code.

I actually used a timer service to run this script everyday at 5 AM. Finally after few days, i started getting very few requests. So thought of sharing the script:

 $listname = "Pages"   
 $url = "http://myWebApp/sites/mySite"  
    
 function approvePublishContent ($w, $listName) {  
  $list = $w.Lists |? {$_.Title -eq $listName}  
  foreach ($item in $list.Items)   
  {
   //Checking if item is locked
   if(($item -ne $null) -and ($item.LockId -ne $null)) {  
    $item.ReleaseLock($item.LockId)  
   }  
   if( $item.File -ne $null) { $itemFile = $list.GetItemById($item.ID).File }  
   else { $itemFile = $list.GetItemById($item.ID) }  
   
   //Checking in the item
   if( $itemFile.CheckOutStatus -ne "None" ) {   
    $itemFile.CheckIn("Automatic CheckIn. (SysAdmin)")  
    if( $item.File -ne $null) { $itemFile = $list.GetItemById($item.ID).File }  
    else { $itemFile = $list.GetItemById($item.ID) }  
   }  

   //Publishing the item
   if( $list.EnableVersioning -and $list.EnableMinorVersions) {   
    $itemFile.Publish("Automatic Publish. (SysAdmin)")  
    if( $item.File -ne $null) { $itemFile = $list.GetItemById($item.ID).File }  
    else { $itemFile = $list.GetItemById($item.ID) }  
   }  

   //Approving it in case approval is required
   if( $list.EnableModeration ) {   
    $itemFile.Approve("Automatic Approve. (SysAdmin)")   
   }  
  }  
 }  
 $site = Get-SPSite $url  
 foreach ( $web in $site.AllWebs )  
 {  
  approvePublishContent $web $listname  
 }  
 Write-Output "OK"  
   

Monday, February 3, 2014

Updating Web part properties using PowerShell in SharePoint

Web part properties define the structure as well as functionality of a web part. They are quite useful while configuring a web part. We have a huge list of web part properties which have been defined by microsoft. you can have a look over these properties from the link below:

SharePoint Web part properties

Now once i ran into a situation wherein i had to change the "ChromeType" property of a web part in the landing page of all the subsites as well as root site in my site collection. There were a total of 32 subsites. So in order to do this through User Interface would have required a considerable amount of time.
SharePoint 2010

So i created a powershell script to do so and voila! I was able to do so in a single shot.

Each web part page is associated with a "SPWebPartManager" class. This class in particular contains references to all the web parts on the page. So in order to access my web part i have to iterate through the "SPWebPartManager" class.

Here the web part name is "Relevant Articles" and the chrome property has to be set to "TitleAndBorder".
  
 //Get reference to the SPSite object
 $SPsite = Get-SPSite "http://mywebapp/sites/mySite"  
   
 //Iterate through all sub sites and root site  
 foreach($SPWeb in $SPsite.AllWebs){  
   
 //Get reference to the landing page. Since it is a publishing site so default.aspx is the landing page  
 $page = $SPWeb.GetFile("Pages/default.aspx")  
   
 //Checkout the page  
 $page.CheckOut()  
   
 //Get reference to the webpartmanager class  
 $webpartmanager = $SPWeb.GetLimitedWebPartManager("Pages/default.aspx",   
 [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)    
   
   
 //Iterate through webparts in webpartmanager class  
  for($i=0;$i -lt $webpartmanager.WebParts.Count;$i++)  {   
   
 //Check for the name of required web part   
  if($webpartmanager.WebParts[$i].title -eq "Relevant Articles")   
  {    
   
     //Get reference to the web part  
     $wp=$webpartmanager.WebParts[$i];  
       
     //Set the chrome property  
     $wp.ChromeType="TitleAndBorder";  
   
     //Save changes to webpartmanager. This step is necessary. Otherwise changes won't be reflected  
     $webpartmanager.SaveChanges($wp);  
       
     break;   
   
  }   
 }   
   
  //Check in and Publish the page  
  $page.CheckIn("Relevant Articles")  
  $page.Publish("Relevant Articles")  
   
  // Update the SPWeb object  
  $SPWeb.Update();   
    
  //Dispose SPWeb object  
  $SPWeb.Dispose();  
 }  

Sunday, February 2, 2014

New Delegate Controls in SharePoint 2013

Delegate Controls are very significant medium to make changes to master page without touching the code part. In SharePoint 2010, we had a lot of delegate controls. To name a few we had : AdditionalPageHead, SmallSearchInputBox etc.

Now in SharePoint 2013, three new delegate controls were introduced. These were actually based on the new master page structure in SP 2013. Since in SharePoint 2013 we have "suites" defined in layout i.e left suite bar and right suite bar, so the delegate controls are based on them.

They may be summarized as below:

  • PromotedActions
  • SuiteBarBrandingDelegate
  • SuiteLinksDelegate

  • PromotedActions delegate control is that part of header which contains links like "Share","Edit" etc. So we can use this delegate control to add our own controls to the header as shown below:

    SharePoint Delegate Controls
    And the code for user control is as simple as :

     <a title="Open Facebook" class="ms-promotedActionButton" style="display: inline-block;" href="http://www.facebook.com">  
     <span class="s4-clust ms-promotedActionButton-icon" style="width: 16px; height: 16px; overflow: hidden; display: inline-block; position: relative;">  
     <img style="position:absolute;" alt="facebook" src="/_layouts/15/images/MyDelegateControls/facebook.png"/>  
     </span>  
       <span class="ms-promotedActionButton-text">Post on Facebook</span>  
     </a>  
    

    SuitingBarBrandingDelegate  Delegate Control facilitates us to override the left-top corner text for the site. By default it is "SharePoint". So we can replace it with the title of our own site:

    SharePoint Delegate Controls


    User Control: (SuiteBarBrandingDelegateCustom ascx)
     <div class="ms-core-brandingText" id="SiteTitleControl" runat="server" />   
    
    Code behind: (SuiteBarBrandingDelegateCustom.ascx.cs)
     protected void Page_Load(object sender, EventArgs e)  
     {  
       SiteTitleControl.Controls.Add(new Literal  
       {  
         Text = string.Format("<a href='{0}'><img src='{1}' alt='{2}' /></a>", SPContext.Current.Site.Url,  
         "/_layouts/15/images/MyDelegateControls/sitelogo.png", SPContext.Current.Site.RootWeb.Title)  
       });  
     }  
    

    SuiteLinksDelegate delegate control allow us to add  links in right suite bar like "Newsfeed","Sites" etc. :

    SharePoint Delegate Controls


    User Control Code Behind:
     protected override void Render(HtmlTextWriter writer)  
       {  
         writer.RenderBeginTag(HtmlTextWriterTag.Style);  
         writer.Write(".ms-core-suiteLinkList {display: inline-block;}");  
         writer.RenderEndTag();  
         writer.AddAttribute(HtmlTextWriterAttribute.Class, "ms-core-suiteLinkList");  
         writer.RenderBeginTag(HtmlTextWriterTag.Ul);  
         RenderSuiteLink(writer, "http://www.myreports.com", "Report", "TimeManagement", false);  
          writer.RenderEndTag();  
         base.Render(writer);  
       }  
    

    Note : For all these delegate controls , you need to add a reference in Elements.xml file to specify the control id and control source properties:
     <?xml version="1.0" encoding="utf-8"?>  
     <Elements xmlns="http://schemas.microsoft.com/sharepoint/">  
      <Control ControlSrc="/_controltemplates/15/MyDelegateControls/UserControl.ascx"  
          Id="DelegateControlID" //ID of DelegateControl e.g. "SuiteLinksDelegate"  
          Sequence="1" />  
     </Elements>  

    Saturday, February 1, 2014

    A list survey discussion board or document library with the specified title already exists error

    A few days ago i came up with a strange error while navigating to Site Settings > Title,Logo and Description in a share point site.

    The error was :

    SharePoint

    I did a lot of digging around but was unable to find the relevant issue. The logs were showing errors like "Exception thrown" or "list not found" etc. Then somewhere in the logs i saw this error

    "The list "$Resources:core,webpageassetList;" in web "http://mysite/site" was not created"

    So it seemed then while enabling the "Wiki Home Page" feature, "Assets Library" was created but somehow lost its context or reference in ContentDB.

    So i deleted the current assets library and re-created it. And finally i was able to resolve the navigation issue.

    Running ECMAScript under Anonymous access

    Client Object Model in SharePoint has been quite significant since its introduction in SharePoint 2010. It does allow us to rapidly build web parts in JSOM/ECMA  with little or no need for compiled code.

    The functionality is quite simple and involves creating some functions and executing them asynchronously. This behavior prevents our browser from freezing until the response has come back from the server.

    Now we need to take care of some important things while creating web parts using ECMAScript. Since the pages would be accessed  by visitors and may also be accessed by anonymous users, so site admins need to take care of the proper permissions.

    Anonymous users , by default,  do not have the privilege of requesting the server for resources even for read only access. One of the example may be like if there is a picture library in the site and a carousel web part on the home page is displaying those pictures . In such cases, while accessing the home page, the anonymous users will get the following error:


    It occurs because anonymous users are restricted on requesting the server for "GetItems" property of the list. This behavior is default for anonymous users.


    So in order to prevent this error, the site admin must execute the following script in powershell:
     $webapp = Get-SPWebApplication “http://somesite/”
     $webapp.ClientCallableSettings.AnonymousRestrictedTypes.Remove([microsoft.sharepoint.splist], "GetItems") 
     $webapp.Update()

    Before doing this make sure "Anonymous Access" is allowed in Web Application:




    Thursday, January 30, 2014

    Web Part cannot be imported.It's is not registered as safe

    While trying to add a custom web part in SharePoint we might come across an error like :

    "A Web Part or Web Form Control on this Page cannot be displayed or imported. The type could not be found or it is not registered as safe"

    SharePoint 2013



    This happens when safe control entries are set to false.

    This behavior can be corrected in two ways:

    1. Adding safe entries in web.config file :

      a. Open web.config
      b. Locate the SafeControls Tag
      c. Make a safe control entry

        <SafeControl Assembly="Assembly name, Version=1.0.0.0, Culture=neutral,    PublicKeyToken=d8eb6481d8b4beec" Namespace="your webpart namespace" TypeName="*" Safe="True" />

    2. Adding safe entries  in SharePointProjectItem.spdata file which can be found in your project    folder: Project Folder-> Module ->spdata file.

     <SafeControl Assembly="Assembly name, Version=1.0.0.0, Culture=neutral,    PublicKeyToken=d8eb6481d8b4beec" Namespace="your webpart namespace" TypeName="*" Safe="True"  />

    In some cases the issue is resolved by following any one of them while in other cases both of these methods need to be implemented.

    Wednesday, January 29, 2014

    Migrating Managed Metadata Term Stores in SharePoint Server across Farms

    While moving a site from development environment to production environment, it is recommended to move MMS term stores too. We can actually adopt two approaches to this:

    1. Export Term Stores in a .csv file and then Import them to target server.
    2. Use a powershell script to create a .cab file to import on target server.

    SharePoint

    The first approach is easier but has a major drawback. It does not persist the GUID of the terms. This may lead to many errors in the imported site because some web parts might be dependent on a term's guid.

    e.g. if i have a CQWP which shows filtered data as per a MMS term, then in the target server the filtering would be lost.

    So a better and safe way is to export and import MMS using Powershell:

    Export

    SharePoint

     Add-PSSnapin Microsoft.SharePoint.Powershell
     $metadataApp= Get-SpServiceApplication | ? {$_.TypeName -eq "Managed Metadata Service"}
     $mmsAppId = $metadataApp.Id

     $mmsproxy = Get-SPServiceApplicationProxy | ?{$_.TypeName -eq "Managed Metadata Service Connection"}
     Export-SPMetadataWebServicePartitionData -Identity $mmsAppId -ServiceProxy $mmsproxy -Path "C:\Users\Desktop\MMD.cab”

    Import


    SharePoint

    Add-PSSnapin Microsoft.SharePoint.Powershell
     $metadataApp= Get-SpServiceApplication | ? {$_.TypeName -eq "Managed Metadata Service"}
     $mmsAppId = $metadataApp.Id

     $mmsproxy = Get-SPServiceApplicationProxy | ?{$_.TypeName -eq "Managed Metadata Service Connection"}

    Import-SPMetadataWebServicePartitionData -Identity $mmsAppId -ServiceProxy $mmsproxy -Path "//SharedPath/Users/Desktop/MMD.cab" -OverwriteExisting;

    NOTE: While importing make sure the .cab file is in a network path accessible to SQL Server with ContentDB and which has been shared with the user account of the MMS Service.

    Problems Adding Apps in SharePoint 2013

    Sometimes adding an app in SharePoint 2013 does not work. It throws an error "Sorry,something went wrong". This can happen due to a lot of reasons. But when i ran through this problem it was because of using a custom master page.




    My custom master page did not have a "Breadcrumb" content placeholder (PlaceHolderTitleBreadcrumb) But "adding apps" expected that content placeholder. So after adding it the problem was resolved.

    Make sure you have all placeholders as below:

    1. DeltaPlaceHolderLeftNavBar
    2. PlaceHolderLeftNavBar
    3. DeltaPlaceHolderPageTitleInTitleArea
    4.  PlaceHolderPageTitleInTitleArea 

    Also each of them should not be set to Visible=False


    The code for the content placeholders are:

    <SharePoint:AjaxDelta id="DeltaPlaceHolderLeftNavBar" BlockElement="true" runat="server">
    <asp:ContentPlaceHolder id="PlaceHolderLeftNavBar" runat="server">
    </asp:ContentPlaceHolder>
    </SharePoint:AjaxDelta
    <SharePoint:AjaxDelta id="DeltaPlaceHolderPageTitleInTitleArea" runat="server">
    <asp:ContentPlaceHolder id="PlaceHolderPageTitleInTitleArea" runat="server">
    </asp:ContentPlaceHolder><asp:ContentPlaceHolder id="PlaceHolderTitleBreadcrumb" runat="server" Visible="false"></asp:ContentPlaceHolder>
    </SharePoint:AjaxDelta>