Monday, February 8, 2016

Using javascript and REST API to create a sub-site cross site collection

The most important thing is to impersonate the current logged user to create a sub-site in another site collection. And that is also a limitation of REST API when execute the code outside the context. In this article, I create a sample code to create a sub-site in another site collection with the same context and using currently digest to authenticate.

Step 1: get context info

If you are using JSOM, you don't need to get this digest because JSOM is already authenticated to the site and just execute the code in the current context. Only if execute the code outside the context and perform cross-domain or outside SharePoint context, this step is required.

$.ajax({
url: me.rootUrl + "/_api/contextinfo",
method: "POST",
headers: {
 "Accept": "application/json; odata=verbose"
},
success: function(data) {
 __REQUESTDIGEST = data.d.GetContextWebInformation.FormDigestValue;
                        },
                        error: function(e) {
                        }
               });

Step 2: create a sub-site

$.ajax({
 url: rootUrl + "/_api/web/webinfos/add",
 type: "POST",
 headers: {
"Authorization" : "BEARER " + __REQUESTDIGEST,
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose",
"X-RequestDigest": __REQUESTDIGEST
 },
 data: JSON.stringify({
'parameters': {
 '__metadata': {
'type': 'SP.WebInfoCreationInformation'
 },
 'Url': "YOUR_URL",
 'Title': "YOUR_TITLE",
 'Description': "YOUR_DESCRIPTION",
 'Language': 1033,
 'WebTemplate': "YOUR_SITETEMPLATE",
 'UseUniquePermissions': true|fale
}
 }),
 success: function(data) {

 },
error: function(data, errorCode, errorMessage) {

}
});

With JavaScript, you must define the key "Authorization" : "BEARER " + __REQUESTDIGEST to authenticate the validation logged. If you work with SharePoint Designer, it should be "Authorization" : "BEARER ". You will get the error "invalid format of Authorization" if you  add the digest after Bearer. To avoid the error in SharePoint Designer, you could define the key Authorization with empty string or leave it with Bearer, not add the digest.

Good luck!

Sunday, February 7, 2016

Fix some errors when working with REST API

Response Code: "400 BadRequest"
Response Message: "A node of type 'PrimitiveValue' was read from the JSON reader when trying to read the start of an entry. A 'StartObject' node was expected"

or

Response Message: {“odata.error”:{“code”:”-1, Microsoft.SharePoint.Client.InvalidClientQueryException”,”message”:{“lang”:”en-US”,”value”:”The property ‘__metadata’ does not exist on type ‘SP.User’. Make sure to only use property names that are defined by the type.”}}}

or

Response Message: {“error”:{“code”:”-1, Microsoft.SharePoint.Client.InvalidClientQueryException”,”message”:{“lang”:”en-US”,”value”:”An entry without a type name was found, but no expected type was specified. To allow entries without type information, the expected type must also be specified when the model is specified.”}}}

This error is very common and used to get from result of REST API in workflow or JSON. The special thing of REST API in SharePoint is no having the same as formatted of command structure.

See example:

Upload file to library

url: http://site url/_api/web/GetFolderByServerRelativeUrl('/Folder Name')/Files/Add(url='file name', overwrite=true)
method: POST
body: contents of binary file
headers:
    Authorization: "Bearer " + accessToken
    X-RequestDigest: form digest value
    content-type: "application/json;odata=verbose"
    content-length:length of post body

Create a list

url: http://site url/_api/web/lists
method: POST
body: { '__metadata': { 'type': 'SP.List' }, 'AllowContentTypes': true, 'BaseTemplate': 100,
 'ContentTypesEnabled': true, 'Description': 'My list description', 'Title': 'Test' }
Headers: 
    Authorization: "Bearer " + accessToken
    X-RequestDigest: form digest value
    accept: "application/json;odata=verbose"
    content-type: "application/json;odata=verbose"
    content-length:length of post body

The difference of those structure is a number of parameters and position of parameters. Some parameters must be transfer by query string and some of properties is passed from body of message. Assume that to upload the file name with the path is too long (over 256 characters), it will throw the error.

In the body of message, sometime we must define the variable named "parameters" to pass them to REST API and sometime it is not necessary. The most important thing is to understand of formatted snippet of REST API for separately command.

 

Example above also throws the error and I have a final solution is to remove the "parameters" from body of message. If you set the method is PUT, that means you must provide all properties of endpoint and X-HTTP-Method = MERGE is not affected. If you need to set some properties and leave some properties to be default or not set, you must set the method to POST and define X-HHTP-Method = MERGE

See the result



Good luck!



Stop/Start workflow for SharePoint Online using PowerShell Script

With SharePoint Online, PowerShell is as a connected bridge so that it itself brings a big dedication. I always think about PS script whenever get a new request.

Start/Start workflow for list item of large list is one of tasks that I have been worked on and it was so excited. This article is just sharing the script code with a little explanation to avoid the error while it's executing.

Common Script

$username = "YOUR_TENANTACC" 
$password = "YOUR_PASS" 
$url = "YOUR_SITE_URL"

$securePassword = ConvertTo-SecureString $Password -AsPlainText -Force 

# the path here may need to change if you used e.g. C:\Lib.. 
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll" 
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll" 
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.WorkflowServices.dll" 

# connect/authenticate to SharePoint Online and get ClientContext object.. 
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($url) 
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword) 
$clientContext.Credentials = $credentials 

$web = $clientContext.Web
$clientContext.Load($web)
$clientContext.ExecuteQuery()

$lists = $web.Lists
$clientContext.Load($lists)
$clientContext.ExecuteQuery()

$lst = $lists.GetByTitle("YOUR_LIST")
$clientContext.Load($lst)
$clientContext.ExecuteQuery()

#get all workflow subscription in your web/sub-site
$wfServicesManager = New-Object Microsoft.SharePoint.Client.WorkflowServices.WorkflowServicesManager($clientContext, $web)

$wfSubscriptionService = $wfServicesManager.GetWorkflowSubscriptionService()
$wfSubscriptions = $wfSubscriptionService.EnumerateSubscriptions()
$wfInstanceSevice = $wfServicesManager.GetWorkflowInstanceService()

$clientContext.Load($wfSubscriptions)
$clientContext.Load($wfInstanceSevice)
$clientContext.ExecuteQuery()

#initalize the parameters for workflow
$dictionary = New-Object 'system.collections.generic.dictionary[string,object]'
$dictionary.Add("YOUR_VARIABLE", "YOUR_VALUE")

#in case, if you need to start workflow on some items, you could execute the query and start on those items    
$qry = New-Object Microsoft.SharePoint.Client.CamlQuery
$qry.ViewXML = "<View><Query><Where>YOUR_QUERY</Where></Query></View>"
                
$items = $lst.GetItems($qry)
$clientContext.Load($items)
$clientContext.ExecuteQuery()

$srb = $wfSubscriptions | Where-Object { $_.Name -eq "YOUR_WORKFLOW_NAME" }

Start Workflow

$cnt = 0

foreach($itm in $items)
{
    $workflowInstances = $wfInstanceSevice.EnumerateInstancesForListItem($lst.ID, $itm.ID)
    $clientContext.Load($workflowInstances)
    $clientContext.ExecuteQuery()

    # bypass the item which the workflow instance was started
    $instance = $workflowInstances | Where-Object { $_.WorkflowSubscriptionId -eq  $srb.Id -and $_.Status -ne "Started" }
    
    if ($instance -ne $null)
    {
        $resultid = $wfInstanceSevice.StartWorkflowOnListItem($srb, $itm.Id, $dictionary)
        $clientContext.ExecuteQuery()
        Write-Host "Started workfkow [" $srb.Name  "] on item ["  $itm.Id  "]: " $resultid.Value -foregroundcolor Green
        Start-Sleep -s 1
        $cnt++
    }
}

Write-Host $cnt " are effected - Done!"

Stop Workflow 

$cnt = 0

foreach($itm in $items)
{
    $workflowInstances = $wfInstanceSevice.EnumerateInstancesForListItem($lst.ID, $itm.ID)
    $clientContext.Load($workflowInstances)
    $clientContext.ExecuteQuery()

    # bypass the item which the workflow instance was started
    $instance = $workflowInstances | Where-Object { $_.WorkflowSubscriptionId -eq  $srb.Id -and $_.Status -eq "Started" }
    
    if ($instance -ne $null)
        {
            $wfInstanceSevice.CancelWorkflow($instance)
            $clientContext.ExecuteQuery()
            Write-Host "Cancel Workfkow [" $instance.Id  "] on item ["  $itm.Id  "] " $instance.Status -foregroundcolor Red
            $cnt++
            Start-Sleep -s 1
        }
}

Write-Host $cnt " are effected - Done!"

Notes
  • Regarding to limitation on SharePoint Online, it only can start 5 workflows instance in a second. So, it should be delayed 1 second for each loop statement.
  • Just start a workflow if the workflow instance did not start and stop workflow if the workflow instance is running.

Saturday, February 6, 2016

Fix the error "Cannot find an overload for "Load" and the argument count: "1"" in PowerShell

PowerShell script is very useful for end-user who wants to work with behind SharePoint (both of on-premise and online). However, user usually gets some troubles if it throws the error during executing the script. The difficulties of coding and working with PowerShell script is to hard debugging and checking somehow.

This error is an example:  

Cannot find an overload for "Load" and the argument count: "1".

It's so weird because the code is always correct (in developer though). If you know that this error only come from the unique reason so that you have no strange and surprise with the funny mistake.

Here is code:

$web = $clientContext.Web
$clientContext.Load($web)
$clientContext.ExecuteQuery()


$lists = $web.Lists
$clientContext.Load($lists)
$clientContext.ExecuteQuery()


$lst = $list.GetByTitle("CheckList")
$clientContext.Load($lst)
$clientContext.ExecuteQuery()


$qry = New-Object Microsoft.SharePoint.Client.CamlQuery
$qry.ViewXML = "<View><Query><Where><And><Gt><FieldRef Name='Due_x0020_Date'/><Value Type='DateTime'><Today OffsetDays='0'/></Value></Gt><IsNull><FieldRef Name='Actual_x0020_Completion_x0020_Da'/></IsNull></And></Where></Query></View>"


$items = $lst.GetItems($qry)
$clientContext.Load($items)
$clientContext.ExecuteQuery()


Be sure it will happen error when it is executed. The error looks like:

Cannot find an overload for "Load" and the argument count: "1".
At C:\Users\...\Downloads\PSScript\Retrieve.ps1:55 char:1
+ $clientContext.Load($item)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest

The root cause of this error come from retrieving the null-able object. That is the variable as a parameter of Load method is null or delivery of that variable is null.

$a = ()
$b = $a.Z()
$c = $b.get_T()
$context.Load($c)

In this example, if $a or $b or $c is null, the error will happen at $context.Load($c) with the message. above.

To fix this, just only take overview of the code and prepare all variables and make sure the name of methods and properties are not miss-spelled and correctly grammar.

Good luck!

Tuesday, August 25, 2015

SharePoint 2016 IT Preview is available

Microsoft has announced the downloadable package of SharePoint 2016 and waiting for getting the feedback from users.

This released is proved that SharePoint is still alive, health and continue grow up with a lot of new features. Some of features is obsoleted and replaced by new better features.


The download package can be downloaded here

The new features will be supported in this releases:

  • Post to Yammer
  • New control for OneDrive Business
  • Site page pinning
  • Site folder view
  • Recycle Bin for OneDrive and Team Sites
  • Images and videos preview
  • Document library with the shortcut keys
  • Web Application Open Platform Interface Protocol (WOPI)


and many updates for old features.


Tuesday, April 14, 2015

SharePoint Saturday Event 8th - The best ever event.

Thank you all of you to attend the #SharePoint #Saturday event at An Nam Cafe, Ho Chi Minh City. The success today is indispensable for your coming, we always sincere respect the precious time that you save for us, for this event. We give a special thank to the sponsors, who helped us organize the seminar being successful. In privately, I would like to say thank you to NIFIT, was accompanied with SPS Viet Nam during 2 years, and QUMU, a Singapore company shared and present for the first time.

With this, SPS Viet Nam opened the wide knowledge in each topic:

  • SharePoint /w internet of things: the new thing in SPS event and in HCMC, I thought! However, if you have a confident idea enough to design an interesting component (I don't know how to define the thing) and run with SharePoint, it may be the most exciting device in some day, and SharePoint will be a transporter! It was introduced by Hoang An Phan from Fablab Sai Gon
  •  Perhaps, your mind just keep the image of Skype, Lync or whatever software for conference with both sound and video. QUMU bring the ability other to communicate in the meeting. That is to use any devices for your connection. Especially, the tool can work on any devices and browser. Their solutions will help you leave the traditional video software's and reach out of the completely comfortable usage.
  • The next interesting in event is how to use SingalR to build a SharePoint real-time application and new UI with AngularJS. This topic opens a variety ideas for new SharePoint solutions or application. The gamification is also the new term in software application industrial, especially for SharePoint, can integrate to/with many tools, techs to have a social part such as Yammer tracking personal actions. In this event, Mr. Tiep introduced a demo about live chating/communicating based on SharePoint webpart.
  • The last session is a deep-dive of manage meta-data for search service. Mr. Binh, from Appvity, presented a way to manage and search the term, and gave many useful examples in real life, real time. This session help us understand more and more about how SharePoint can handle the term and apply to search service. So great!
We are so sorry about the missing T-Shirts and seats for audiences because we do only forecast about 80-100 attendees. However, the game is over! So crowed!

















 
Finally, thank you all speakers in the 8th of SPS Viet Nam. Hopefully, in the next event, we will have more exciting topics for small and average company which are considered transfering from other to SharePoint. Please follow us to get started with SharePoint and improve your value in managing the company.

Wednesday, April 1, 2015

Explain the abbreviation in SharePoint

Regarding to request from my friends having the explanation of abbreviation in SharePoint. This may not totally enough but it might help you know clearly when you read the document.


  • WAD: work as design. You were surprised of strange thing when you do something on SharePoint list or page. You think different and the result must be like your thought. E.g: When you switch from Subject view of discussion list in SharePoint 2013 to Management view, you think that the page will redirect to flat or thread view. But the result was not shown the same as your though. It redirects to itself and you see the item was clicked to be a folder. It calls SharePoint WAD.
  • OOTB: out-of-the-box. This term lets you know what SharePoint support. E.g: In the discussion list of SharePoint 2013, it was integrated the Like and Rating for SP Office Server version. You needn't install any 3rd-party to support the rating and like functioning for this list. This function is called SharePoint OOTB. Almost SharePoint software company produce a product or customize or give a solution are having the idea to support the functioning that SP OOTB does not have.
  • CSOM: client side ojbect model. This abbreviation is related to the program is run on client side. E.g: You want to create a console or windows form to access to SharePoint site and SharePoint server is working as remoting. You can use C# or VB to develop the program and, of course, SharePoint always support the DLL for your reference to the code.
  • JSOM: javascript object model. This model works only in the SharePoint application page or web part, or whatever you need to run in the web page.The objects is built in the SharePoint's JS files in the layouts folder of 15/hive (14/hive). E.g: You build a web part and you need to access the list at the run-time, you could implement something like this:
          var web = SP.ClientContext.get_current().get_web();
  •  REST API: Representational State Transfer API. Think of it simple like coding by javascript, vb or c#. Actually you have to use javascript object to access the SharePoint items. A technical named RESTful will help you understand a deep knowledge base of this term. However, you can image that you can access to all SharePoint objects site by using an address and the method of client context. REST API just only support on SharePoint 2013 and SharePoint online (Office 365). For more information, click  on REST API reference and samples. For SharePoint 2010, you could get and install MashPoint REST by Bamboo Solutions. REST API helps you access the site anywhere, easy to learn, safe in work and fast on time.
         For more information of REST vs CSOM, visit AndrewConnel blog
  • Built-in: This term means you don't need to customize anymore. Just get and build. E.g: You need to build a custom column with a compatibility functioning in the backend, but it's so simple in the new/edit/display form because you only use the controls that SharePoint has been supported. That calls built-in controls.
  •  More...
Hey guys, please let me know more abbreviation!

Tuesday, March 31, 2015

SPS VietNam: April 11, 2015 - Don't miss! Last chance!

It's really hard to hold the event for SharePoint in Viet Nam. Having no more connection between company and SharePoint community/group. We, SPS and SPUG, always bring the knowledge to share with all IT support, IT manager, developers and others who are working in IT industry. SPS Viet Nam is a popular communication about SharePoint in Viet Nam and this organization always hanlde the SharePoint events. It's completely free!

Finally, the next event is coming soon on April 11, 2015.
Don't miss!
Last chance!


Regist here: 


Free!

Monday, March 30, 2015

List Definition was changed the schema for existing lists!

Until now, I did not know exactly the processing of deployment list definition and there is any changes on each of SharePoint version. I have scenario that I am facing the problem with migration and upgrading list definition. Just is:

I create a list definition based on custom list, because I need to declare all fields, views and the user interface rendering. It's actually basically and for testing purpose only.

The list has only one column named "Title" as default, because I do not know what the next column is to do, so I will upgrade the list def later. I called the list /w version 1.


I modified the list definition schema to add more fields:


Then, from Visual Studio (version 2012) context menu, I click to deploy directly to site. Of course yes if I create a new list base on my list definition having new schema with new 2 columns. But I get the warning that the list definition is created before deployment will be delete the schema and effect to new schema from Visual Studio:


That means all my existing lists will be effected to new schema and they work correctly. The result looks like this:


The question is if I don't use Visual Studio to deploy directly to my server in many scenarios, what happen on my existing lists? for example: some of deployment tools just do copy a schema to physically installation folder and then do reset the IIS or even executed the stsadm command to deploy from wsp. I have tried to do some tests by copy/paste the new schema to feature folder and then execute iisreset command (and deploy by executing stsadm command to deploy wsp). As a result I can still see my 2 new fields in the list settings, however, they did not work correctly. Basically, to access the value of SPListItem, it will throw an exception "Object is not set reference...". It's right because it does not have the default value and it's added after item was created.

The most important thing is if we don't use Visual Studio to upgrade the lisf definition, what do we need to do upgrading the existing lists?

Solutions: After deployment process finish, the all existing lists are effected with the new schema, thus, to determinate the old lists must be based on the other information of the list with specific scenario. For example: properties bag of list/field does not change after deployed the new updates, or checking the dependency to update the old list.

  • fields: add/remove/update by code
  • data: using Batch update command to avoid the performance issue.

SHOULD NOT DO: 
  • Do not delete the field and then add the new field if the old field and new field has the same as schema.
  • Move data from old field to new field because it will happen performance issue. In the feature activating/upgrading process, there is not enough time to upgrade the data for large list. 











Wednesday, February 11, 2015

Stuck in stupid with the error "Object does not support this method..."

Sometime I got the stuck in coding and it seems taking waste time to google or ask for help in forum. Eventually I found the stupid reason that I don't think about the basically knowledge.

Look at the code:


var clientContext = SP.ClientContext.get_current();
var list = clientContext.get_web().get_lists().getByTitle(context.ListTitle);
                
I got the error "Object does not support this method..." bla bla bla. Now, I know you will ask me in your mind the question is where the code is put in! For being time, I cannot answer your question unless I could resolve the problem.

After doing a forage in the internet, I remember the terrible reality suddenly. I forgot initializing the object SP.ClientContext in the sp.js! Wow hooooo....That code was changed:



SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
        var clientContext = SP.ClientContext.get_current();
        var list = clientContext.get_web().get_lists().getByTitle(context.ListTitle);
               .....
});
                

Done!
Everything is resolved!