Tuesday, 15 November 2016

Revisiting concepts of JavaScript for SharePoint / Office 365 developer - Part 1 - JavaScript variables

Hi All,


In this article I’ll go through the basics of JavaScript variables, important points, which should know for SharePoint / Office 365 developer who uses the JavaScript Object Model(JSOM) for SharePoint / Office 365 development.

Background: While working on one of the SharePoint online project I realized that its not sufficient only knowing the SharePoint and respective SDKs. Now a days In development of SharePoint / Office 365 importance of JavaScript is increased a lot, in order to avoid custom server side coding, sand box solutions are deprecated, new App model development, performance, migration becomes easy etc.  
 
One important scenario which I found where we have added two JSOM web parts (content editor with JSOM) on one of the our SharePoint online page and both the webparts stopped working. When we have only any one web part on the page it was working fine but when we have both the web parts on the page, none of the web part is working. After looking into details it found that its JavaScript issue, same variable names in both the web parts .JS file, JavaScript namespaces are not used, “Strict” keyword is not used etc.
 
So I thought why not to share the basics of JavaScript which SharePoint /Office 365 developer should aware at least. I’ll start with very simple, JavaScript variables (though this is very important point) and in coming articles with move ahead with advanced topics which are useful for SharePoint / Office 365 development.

JavaScript variables:

  1. JavaScript variables are declared with “var” keyboard like
    var counter=0;
    JavaScript dosent have specific data type keyword.
     
  2. If there is no specific custom namespace specified or variable is defined outside the function then variable is defined in global namespace. Its a global variable. But if variable is defined in any function then its local variable.
     
  3. The scope of Global variable is till the our page is loaded where script is added. As we move on another page scope of global variable ends. If we reload the page again all our global variables scope ends and created again.
     
  4. If we use variable without declaring those then these variables are global variables. That means if we use variable in function without declaring it, till variable is available outside the function. So its really important to declare the variables.
     
  5. Its best practice to use local variables unless and until we requires global variables. Or at least we must specify custom namespaces as explained in point 6.
     
  6.  We can define the variable in custom namespace as
         
     <script type= "text/javascript">
    "use strict";
    //Custom NameSpace
     var MyCustomNameSpace = window.MyCustomNameSpace || {};
     var MyCustomNameSpace .cssFileURL = "CSS File URL";
      </script>
     
       Here, we have created custom namespace “MyCustomNameSpace ” and defined variable “cssFileURL” in the namespace.
     
    We can access above variable directly as - MyCustomNameSpace .cssFileURL
     
  7. Its really very important to use proper namespace name as per the functionality whenever using the JSOM. It avoids collision of variables if two JSOM web parts are added on the same page and variable names are same.
     
  8. typeof operator is used to get the variable type as
    alert(typeof MyCustomNameSpace .cssFileURL);
Above line will return the ”string” type of MyCustomNameSpace .cssFileURL variable as
Figure 1 : Using typeof operator
typeof operator returns one of the following types
 
object
string
number
boolean
function
object
       Undefined

9. JavaScript variables are case sensitive. Not only variables but function names, keywords etc. are also case sensitive. This means variable item is different than variable Item. So it really matters to user proper variable naming conventions when we use variables.

Here I try to cover all the required details regarding JavaScript variables. If you think any more important point which is missed here then please include in comments section.
 
Thanks!
 
Enjoy Reading :)
 
As usual any comment / suggestions / feedback / questions always welcome :)



Thursday, 10 November 2016

SharePoint Online / Office 365 - Resolved exception "Method not found: 'Boolean System.Net.WebResponse.get_SupportsHeaders()'."

Hi All,

In this article, I’ll explain how we resolved exception "Method not found: 'Boolean System.Net.WebResponse.get_SupportsHeaders()'." while calling “ExecuteQuery” method of ClientContext in PowerShell script while executing against SharePoint online / Office 365. Finally I’ll also share the software requirements to access/manage/connect Office 365/SharePoint online and few references.

Background: We have writing one PowerShell script and testing in between to verify the result.

Following is the sample code snippet we executed and ran the script.
# add references to SharePoint client assemblies and authenticate to Office 365 site - required for CSOM
 
 Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
 
  Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
 
#Specify tenant admin and URL
$User = "" # Your tenant user id goes here
 
#Configure Site URL and User
$SiteURL = "" #Your tenant site URL
 
#Password
$Password =" " #Password
 
#Convert password to secure string
$securePassword = ConvertTo-SecureString -String $Password -AsPlainText –Force
 
$Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$securePassword)
 
#Instantiating the client context object and setting the credentials 
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Context.Credentials = $Creds
 
#Getting web instance and loading it
$web = $clientContext.Web
 
$clientContext.Load($web)
$clientContext.ExecuteQuery()

Issue: Issue is in above PowerShell script we are getting following exception on $clientContext.ExecuteQuery()


Exception calling "ExecuteQuery" with "0" argument(s): "Method not found: 'Boolean System.Net.WebResponse.get_SupportsHeaders()'."
At C:\PowerShell\Mostlyused.ps1:73 char:1
+ $clientContext.ExecuteQuery()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : MissingMethodException


This exception took us lot of time to solve so thought to share :)

Solution: We are really wondering why suddenly such error is coming since PowerShell scripts were running fine before. We already executed lots of scripts without any issues.

We verified UserName, PassWord, SiteURL and everything seems to be fine. We googled a lot bit but no luck.
 
Only thing we realized that my laptop was formatted and support team installed the .Net Framework, client component SDK and following modules that are required for Office 365, SharePoint Online
After again looking at software installed I realized that there is .Net Framework 4 is installed but to access/manage/connect to Office 365/SharePoint online we need .Net Framework 4.5.x. We have installed .Net Framework 4.5 and script executed successfully without any issue.

Here, I’ll share complete list of required SWs required for accessing/managing/connecting to Office 365/SharePoint online using PowerShell
  1. Windows (64 bit)
    1. Windows 7 with service pack1
    2. Windows 8 or Windows 8.1
    3. Windows server 2008 R2 SP1
    4. Windows server 2012 or Windows server 2012 R2
       
  2. .Net Framework 4.5.x - Installing the .NET Framework
     
References: Connect to all Office 365 services in a single Windows PowerShell window - https://technet.microsoft.com/en-us/library/dn568015.aspx 
 
Manage Office 365 with Office 365 PowerShell - https://technet.microsoft.com/en-us/library/dn568031.aspx 
 
Getting started with Office 365 PowerShell - https://technet.microsoft.com/en-us/library/dn568011.aspx 
 
Office 365 PowerShell for SharePoint Online - https://technet.microsoft.com/library/fp161362.aspx 
 
Thanks!
 
Enjoy Reading :)
 
As usual any comment / suggestions / feedback / questions always welcome :)

Tuesday, 8 November 2016

Office 365 / SharePoint online - PowerShell script to call Search API and get the result

Hi All,

In this article, I'll explain using KeywordQuery class from PowerShell script and write results to .CSV file.  I’ll also explain the scenario where we need to use Search from the PowerShell script.

Scenario :  Our client have Office 365 tenant and very heavily using SharePoint online. We have one big SharePoint online site collection. Site collection having lots of content and there is also  unwanted content available. Customer wants to cleanup the site collection. Customer requested to get all the items/documents which are not updated since last year. Customer also want the view count / open count for respective list items and documents.

One thought came to mind is -  Audit Reports which we supposed to use in On Premises version. So we went to Site Settings >> Site Collection Administration >> Audit log reports (https://myTenant/_layouts/15/Reporting.aspx?Category=Auditing)
 
But in SharePoint online Audit log reports dosent works, it says as following image, even though Auditing is enabled.
Figure 1 : SharePoint Online : Audit Log Report
These audit reports never worked for us in SharePoint online. So option remains using Search and manage meta data property ViewsLifeTime” and “ViewsLifeTimeUniqueUsers”. We configured the Content Search webpart and could see the result for some data. For some data these properties didn’t returned any result.

Our customer wants the result in excel sheet and its really difficult to get content search webpart result in excel sheet though we can write from display template.
 
Finally we decided to write the PowerShell script and call the search APIs like KeywordQuery from the PowerShell script.  
 
Here, I’ll explain step by step how to call search APIs from PowerShell script.

Step 1 : Load the required libraries
# add references to SharePoint client assemblies and authenticate to Office 365 site - required for CSOM
 
 Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
 
  Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
 
  Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Search.dll"

Step 2: Set the required variables like root SiteCollection URL , tenant admin UserName and Password of your site to connect as
 
#Specify tenant admin and URL
$User = "" 
 
#Configure Site URL and User
$SiteURL = ""
 
#Password
$Password =" "
 
$securePassword = ConvertTo-SecureString -String $Password -AsPlainText –Force
 
$Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$securePassword)

Step 3: Get the Microsoft.SharePoint.Client.ClientContext instance and set the credentials as
 
#client context object and setting the credentials 
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Context.Credentials = $Creds

Step 4: Creating instance of KeywordQuery class and setting, selecting the properties
 
 #Calling Search API - Create the instance of KeywordQuery and set the properties
$keywordQuery = New-Object Microsoft.SharePoint.Client.Search.Query.KeywordQuery($Context)
 
 #Sample Query - To get the last year result
$queryText="Path:https://MySitePath/ AND LastModifiedTime<2015-11-05 AND Created<2015-11-05"
$keywordQuery.QueryText = $queryText
$keywordQuery.RowLimit=500
$keywordQuery.TrimDuplicates=$false
$keywordQuery.SelectProperties.Add("LastModifiedTime")
$keywordQuery.SelectProperties.Add("ViewsLifeTime")
$keywordQuery.SelectProperties.Add("ModifiedBy")
$keywordQuery.SelectProperties.Add("ViewsLifeTimeUniqueUsers")
$keywordQuery.SelectProperties.Add("Created")
$keywordQuery.SelectProperties.Add("CreatedBy")
$keywordQuery.SortList.Add("ViewsLifeTime","Asc")

Step 5 : Creating instance of SearchExecutor class and getting the result
 #Search API - Create the instance of SearchExecutor and get the result
$searchExecutor = New-Object Microsoft.SharePoint.Client.Search.Query.SearchExecutor($Context)
$results = $searchExecutor.ExecuteQuery($keywordQuery)
$Context.ExecuteQuery()
#Result Count
Write-Host $results.Value[0].ResultRows.Count

Step 6: Writing result to CSV file
 #CSV file location, to store the result
$exportlocation = "G:\MCH\MCHS Marketing Team details\Admin_ViewsCount.csv"
 
foreach($result in $results.Value[0].ResultRows)
{
$outputline='"'+$result["Title"]+'"'+","+'"'+$result["Path"]+'"'+","+$result["ViewsLifeTime"]+","+$result["ViewsLifeTimeUniqueUsers"]+","+$result["CreatedBy"]+","+$result["Created"]+","+$result["ModifiedBy"]+","+$result["LastModifiedTime"]
    
Add-Content $exportlocation  $outputline 
}

Thanks!
 
Enjoy Reading :)
 
As usual any comment / suggestions / feedback / questions always welcome :).