Tuesday, 28 June 2016

Map Term Set To Metadata Site Column On SharePoint Using JavaScript Object Model


In this post, you will learn how to map a SharePoint taxonomy term set to a metadata site column using JavaScript Object model on SharePoint 2013 / SharePoint 2016 / SharePoint online sites like O365.

The basic idea of the article is to show how we can automate the mapping process of the term set to the site columns.
Load the required script files with the following snippet:
  1. var scriptbaseURL = _spPageContextInfo.webServerRelativeUrl + "_layouts/15/";  
  2. $.getScript(scriptbaseURL + "SP.Runtime.js",  
  3.     function ()
  4.    {  
  5.         $.getScript(scriptbaseURL + "SP.js"function()
  6.         {    
  7.             $.getScript(scriptbaseURL + "SP.Taxonomy.js", GetTermSet);    
  8.         });  
  9.     }  
  10. ); 
Here, we will see how we can retrieve the term sets from the metadata termstore and assign it to the metadata site column.

Get Term Set:
Let us first see how we can retrieve the term set from the taxonomy term store, using the term store name and the term set name. 
  • Get the current context of the site. Using taxonomy and taxonomy session objects, get the taxonomy session of the current site context.
    1. var ctx = SP.ClientContext.get_current();  
    2. Session = SP.Taxonomy.TaxonomySession.getTaxonomySession(ctx);  
  • From the taxonomy session, get the term stores. From the term store collection, retrieve the exact term store by using the term store name. In our case, the term store name is "Managed Metadata Service".
    1. var termStores = taxSession.get_termStores();  
    2. termStore = termStores.getByName("Managed Metadata Service");  
  • From the term store; retrieve the groups. From the groups collection; retrieve the exact group by passing the group name. In our case, the group name is "Testing".  
    1. var groups = termStore.get_groups()  
    2. var group = groups.getByName("Testing")  
  • From the group, retrieve all the term sets. From the term set collection, get the respective term set by passing the term set name. The term set name in our case is "Test".
    1. var termSets = group.get_termSets()  
    2. termSet = termSets.getByName("Test")  
  • Load the term store, the term set objects and execute with the context to retrieve the required values. Here, we require the term store ID and term set ID. These properties are used to assign to the metadata site column properties.
    1. ctx.load(termStore);  
    2. ctx.load(termSet);  
    3. ctx.executeQueryAsync(function(){  
    4.         termStoreId = termStore.get_id();  
    5.         termSetId = termSet.get_id();  
    6.         MapTermSet();  
    7.     },function(sender,args){  
    8.   
    9.          console.log(args.get_message());  
    10.   
    11. });  
Here, the names are used for the term store and the term set instead of IDs, because the term store ID and term set id will change from Server to Server and the names will be the same. The names are common, because the users add it to the taxonomy store. 


Mapping Term Set to Site Column:
Now, we will see how we can map the above term set to the site column.
  • Get the current context of the site, retrieve the Web object and from the object, get the fields collection.
    1. var ctx = SP.ClientContext.get_current();  
    2. var web = ctx.get_web();  
    3. var fields = web.get_fields();  
  • Using field collections, retrieve the exact column by name with getByName method. In this case, column name is "TestColumn".
    1. field = fields.getByInternalNameOrTitle("TestColumn");  
  • Cast the field to the taxonomy field. In the taxonomy field, set the term set ID and the term store ID of the term set. (Use values from the section, given above).
    1. txField = ctx.castTo(field, SP.Taxonomy.TaxonomyField);  
    2. txField.set_sspId(termStoreId);  
    3. txField.set_termSetId(termSetId);  
  • Update and execute the query with the context to finalize the changes.
    1. txField.update();  
    2. ctx.executeQueryAsync(function(){                        
    3. },function(sender,args){      
    4.       console.log(args.get_message());    
    5. });  
The above operation will just set the term set to metadata site column at the site level. The columns inherited at the list level will not be changed. To make the changes of the site columns at the list level, we need to use the updateAndPushChanges(true), instead of update() method.
Now, if you open the site column, you will see the term set called "Test" is mapped to the site column "TestColumn" in the term set settings section.
The code snippet given below shows the entire view for the operations, mentioned above.
  1. var scriptbaseURL = siteurl + "/_layouts/15/";  
  2. $.getScript(scriptbaseURL + "SP.Runtime.js",  
  3.     function () {  
  4.         $.getScript(scriptbaseURL + "SP.js"function(){  
  5.             $.getScript(scriptbaseURL + "SP.Taxonomy.js", GetTermSet);  
  6.         });  
  7.     }  
  8. );  
  9. var termStore = "";  
  10. var termStoreId = "";  
  11. var termSet = "";  
  12. var termSetId = "";  
  13. function GetTermSet(){  
  14.     var ctx = SP.ClientContext.get_current();  
  15.     var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(ctx);  
  16.     var termStores = taxSession.get_termStores();  
  17.     termStore = termStores.getByName("Managed Metadata Service");  
  18.     var groups = termStore.get_groups()  
  19.     var group = groups.getByName("Testing")  
  20.     var termSets = group.get_termSets()  
  21.     termSet = termSets.getByName("Test")  
  22.       
  23.     ctx.load(termStore);  
  24.     ctx.load(termSet);  
  25.     ctx.executeQueryAsync(function(){  
  26.             termStoreId = termStore.get_id();  
  27.             termSetId = termSet.get_id();  
  28.             MapTermSet();  
  29.         },function(sender,args){  
  30.           console.log(args.get_message());  
  31.     });  
  32. }  
  33. var field = "";  
  34. var txField = "";  
  35. function MapTermSet(){  
  36.     var ctx = SP.ClientContext.get_current();  
  37.     var web = ctx.get_web();  
  38.     var fields = web.get_fields();  
  39.     field = fields.getByInternalNameOrTitle("TestColumn");  
  40.     txField = ctx.castTo(field, SP.Taxonomy.TaxonomyField);  
  41.     txField.set_sspId(termStoreId);  
  42.     txField.set_termSetId(termSetId);  
  43.     //txField.update();  
  44.     txField.updateAndPushChanges(true);  
  45.     ctx.executeQueryAsync(function(){                         
  46.     },function(sender,args){      
  47.           console.log(args.get_message());    
  48.     });  
  49.  

Note: This is applicable for SharePoint 2013 or SharePoint 2016 or SharePoint online sites. 

Wednesday, 22 June 2016

Map Term Set to Site Column on SharePoint using CSOM PowerShell


We will see how to map SharePoint taxonomy term set to a Site column using CSOM with PoweShell on SharePoint 2013 / SharePoint 2016 / SharePoint Online sites.

The basic idea of the article is to show how we can automate the mapping process of term set to site columns.


Steps Involved:

The following prerequisites need to be executed before going for any operations using CSOM PowerShell on SharePoint sites. 
  1. Add the references using the Add-Type command with necessary reference paths. The necessary references are Microsoft.SharePoint.Client.dll, Microsoft.SharePoint.Client.Runtime.dll and Taxonomy dll.
    1. Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"  
    2. Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"  
    3. Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Taxonomy.dll"  
  2. Initialize client context object with the site URL.
    1. $siteURL = ""  
    2. $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteURL)  
  3. If you are trying to access SharePoint Online site then you need to setup the site credentials with credentials parameter and load it to the client context.
    1. #Not required for on premise site - Start    
    2. $userId = "abc@abc.onmicrosoft.com"    
    3. $pwd = Read-Host -Prompt "Enter password" -AsSecureString    
    4. $creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($userId, $pwd)    
    5. $ctx.credentials = $creds    
    6. #Not required for on premise site - End    
  4. If you are trying to access the SharePoint on premise site then the credentials parameter is not required to be set to the context but you need to run the code on the respective SharePoint Server or you need to pass the network credentials and set the context.
    1. #Credentials for on premise site - Start    
    2. $pwd = Read-Host -Prompt "Enter password" -AsSecureString    
    3. $creds = New-Object System.Net.NetworkCredential("domain\userid", $pwd)    
    4. $ctx.Credentials = $creds    
    5. #Credentials for on premise site - End    
Before executing below steps, the site column’s Term Setting will look like the image below.

Now we will see how we can retrieve term sets from the term store and assign it to the site column.


Retrieve Term Sets:

The below logic retrieves term set called "Test" from the taxonomy term store. 
  1. Get taxonomy session object by loading and executing the context.
    1. $taxStore = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($ctx)  
    2. $ctx.Load($taxStore)  
    3. $ctx.ExecuteQuery()  
  2. Get the term store by using term store name and term store collection object.
    1. # Retrieve Term Stores & Groups  
    2. $termStores = $taxStore.TermStores.GetByName("Managed Metadata Service")  
    3. $ctx.Load($termStores)  
    4. $ctx.ExecuteQuery()  
    5. $termStore = $termStores[0]  
    6. $Groups = $termStore.Groups  
    7. $ctx.Load($termStore)  
    8. $ctx.Load($Groups)  
    9. $ctx.ExecuteQuery()  
  3. Get the appropriate group where term sets are available by using group name and group collection object. From the selected group, select the term set from the term set collection and term set name.
    1. # Retrieve Term Set & Update Site Column with TermSet  
    2. $Group = $Groups.GetByName("Testing")  
    3. $termSet = $Group.TermSets.GetByName("Test")  
    4. $ctx.Load($termSet)  
    5. $ctx.ExecuteQuery()  
We got the term set. Now we will see how we can map it to site column called "Test".

Mapping Term Set to Site Column:
  1. From the context, get the root web object. Then get the fields. From the field collection, get the respective field with the field name.
    1. $web = $ctx.Site.RootWeb  
    2. $field = $web.Fields.GetByTitle("Test")  
  2. We need to cast the field object to taxonomy field by invoking generic methods. For this we will use MakeGenericMethod along with GetMethod. Here we will use Taxonomy Field object for casting field object.
    1. $field = [Microsoft.SharePoint.Client.ClientContext].GetMethod("CastTo").MakeGenericMethod([Microsoft.SharePoint.Client.Taxonomy.TaxonomyField]).Invoke($ctx, $field)  
  3. Then we can assign the term set and store id of the term set identified from the above section to the field by following code snippet.
    1. $field.SspId = $termStore.Id   
    2. $field.TermSetId = $termSet.Id   
  4. Then update field, load objects and execute the query to complete processing.
    1. $field.Update()  
    2. $ctx.Load($web)  
    3. $ctx.Load($field)  
    4. $ctx.ExecuteQuery()  
Here we have mapped the term set to corresponding site column. The below image shows the term set mapping to site column.

The above set of operations will help in mapping the term set of taxonomy to managed metadata site column. But this will not affect the columns already created at list level using the above site column. For updating the list level metadata columns with the same changes, we need to explicitly use an update operation, where it will push the changes from site level to list levels. Instead of giving $field.update() in the above code, we need to give $field.UpdateAndPushChanges($true). This will make changes available for list columns already created.


Sunday, 19 June 2016

Retrieving videos from o365 video portal in multiple ways

In this post, we will see how we can retrieve videos and related information from o365 video portal with multiple ways. First we will see how we can retrieve all the videos from the portal using content type and also we will see how we can retrieve videos from the portal with multiple filters.


Retrieve All Videos Using Site Content Type ID:

The videos are stored on the portal using cloud video content type. At the video library (list level), the cloud video content type will differ for multiple channels. Also this content type will differ on various sites. Video cloud content type is present at site level. The content type id of video cloud will be common for any o365 portal. The content type id is 0x010100F3754F12A9B6490D9622A01FE9D8F012. It is 40 digits.

At the library level, the video cloud content type id consists of 74 digits. But first 40 digits will be common, since the list level video cloud content type is inherited from site level video cloud content type.

Using REST Search API, the all the videos present across various channels can be retrieved from the portal in a single call with site level cloud video content type. In the query text, we will pass the content type id by appending '*'. So that all the videos which has the content type starting with the same digits will be retrieved.

The Search API will be,
/_api/search/query?QueryText=%27contenttypeid:0x010100F3754F12A9B6490D9622A01FE9D8F012*%27

The results are based on search indexing. The crawl should run periodically to get the video results. And also the properties retrieved here will be more focused on analytical information with some basic video properties. The information like processing status, video running time, channel information will not be retrieved here.  

The following code snippet shows the JQuery Ajax call to get the videos from Office 365 video portal, using REST search API:

  1. $.ajax({  
  2.     url: "/_api/search/query?QueryText=%27contenttypeid:0x010100F3754F12A9B6490D9622A01FE9D8F012*%27",  
  3.     type: "GET",  
  4.     async: false,  
  5.     headers: { "accept""application/json;odata=verbose" },  
  6.     success: function(data){  
  7.         var videosInfo = data.d.query.PrimaryQueryResult.RelevantResults;  
  8.           
  9.         console.log("Available Videos Count on Channel : " + videosInfo.RowCount);  
  10.     var videoResults = videosInfo.Table.Rows.results;  
  11.     for(var i = 0; i< videoResults.length; i++){  
  12.         console.log("Title : "+videoResults[i].Cells.results[3].Value);  
  13.         console.log("Created By : "+videoResults[i].Cells.results[4].Value);  
  14.         console.log("Video URL : "+videoResults[i].Cells.results[6].Value);  
  15.     }  
  16.     //Similarly other results can be retrieved and displayed  
  17.     },  
  18.     error: function(data){  
  19.     }  
  20. });  

The necessary parameters can be only be retrieved using selectProperties option in the API. The example looks like, 
/_api/search/query?QueryText=%27contenttypeid:0x010100F3754F12A9B6490D9622A01FE9D8F012*%27&selectproperties=%27Title%27


Retrieve Videos using Video & List APIs:

The REST Video API used to retrieve the videos from channel will be,
https://videoportalurl/_api/VideoService/Channels('channelid')/GetAllVideos

Here we will see various ways to filter out the videos from the portal. 

The video results here are instant results. More information like processing status, video download URL, owner details, running information, tags, channel and other basic information can be retrieved instantly. Here we can get the required parameters for videos using select parameters. The properties which are retrieved from the operation can be used in the select parameters to retrieve only specific information. For example, in the following example, we have retrieved only file name and video url using the REST API.

User can apply following use cases for retrieving videos. 
  • User can get only playable(processed) videos by applying processing status filter. (VideoProcessingStatus:2)
  • User can get only incomplete videos by applying the status filter (Not processed). (VideoProcessingStatus:1)
  • Filter only videos with the known property values. (AnyProperty:Value)
  • Most played videos (Sort Asc/desc using VideoDurationInSeconds)
 There are many other scenarios where filter and other parameters can be used to retrieve videos with REST Video API. These filter functionalities are available with REST List API as well. 

The API will look like,
https://videoportalurl/_api/VideoService/Channels('channelid')/GetAllVideos?$select=FileName, ServerRelativeUrl,Author&$expand=Author/Name&$filter=VideoProcessingStatus eq 2

OR

https://channelsiteURL/_api/web/lists/GetByTitle('Videos')/Items?$filter= VideoProcessingStatus eq 2

Both the above API will get same set of JSON response, which can be processed and displayed. But the response is different from search API response.

The following code snippet shows the Jquery Ajax call to get the videos present on the specified channel with filters and select parameters, using REST List API:
  1. $.ajax  
  2. ({    
  3.     url: "https://chennal_url/_api/web/lists/GetByTitle('Videos')/Items?$select=Title&$filter=VideoProcessingStatus eq 2",    
  4.     type: "GET",    
  5.     async: false,    
  6.     headers: { "accept""application/json;odata=verbose" },    
  7.     success: function(data){    
  8.         if(data.d != null && data.d.results.length > 0){    
  9.             var videoResults = data.d.results;    
  10.                 
  11.                 
  12.         for(var i = 0; i< videoResults.length; i++){    
  13.             console.log("Title : "+videoResults[i].Title);      
  14.         }    
  15.     }    
  16.     //Similarly other results can be retrieved and displayed    
  17.     },    
  18.     error: function(data){    
  19.     }    
  20. });   
The following code snippet shows the Jquery Ajax call to get the videos present on the specified channel with filters and select parameters, using REST Video API:
  1. $.ajax({  
  2.     url: "https://videoportal_url/_api/VideoService/Channels('channelid')/GetAllVideos?$select=Title&$filter=VideoProcessingStatus eq 2",  
  3.     type: "GET",  
  4.     async: false,  
  5.     headers: { "accept""application/json;odata=verbose" },  
  6.     success: function(data){  
  7.         if(data.d != null && data.d.results.length > 0){  
  8.             var videoResults = data.d.results;  
  9.             for(var i = 0; i< videoResults.length; i++){  
  10.                 console.log("Title : "+videoResults[i].Title);  
  11.             }  
  12.         }  
  13.         //Similarly other results can be retrieved and displayed  
  14.     },  
  15.     error: function(data){  
  16.     }  
  17. });  

Note: Thus you have learned how to retrieve video details using REST search, REST video and REST list APIs with filter and select parameters. Also we understood the basic difference in getting the response using various REST API methods.