Wednesday, March 5, 2014

View Tenant (ULS) Logs in SharePoint Online using CSOM

A while ago, I came across the Office365 UserVoice site. It was a good way to give feedback and let the SharePoint/Office365 team know which features could make the life of SharePoint Developers easy.

I decided to post on it a feature request, which I felt was desperately needed and would really help me as a SharePoint Developer: A way to view ULS Logs on SharePoint Online
http://officespdev.uservoice.com/forums/224641-general/suggestions/4578386-provide-a-way-to-view-uls-logs-on-sharepoint-onlin

It seems this was a shared opinion among many people and the request went on to become one of the top voted on the site:
http://officespdev.uservoice.com/forums/224641-general/filters/top

Fast Forward to today and I was really excited about the SharePoint Conference 2014! I saw a lot of code samples and articles being published as a result of the new features introduced by the SharePoint Team. While exploring the Office App Model Samples (http://officeams.codeplex.com/) I came across the following DLL: Microsoft.Online.SharePoint.Client.Tenant.dll

You can refer to my previous post about using this DLL to create Site Collections in SharePoint Online:
http://www.vrdmn.com/2014/03/create-site-collections-with-csom-in.html

I opened up the DLL in ILSpy and immediately noticed the TenantLog class:
http://msdn.microsoft.com/en-us/library/microsoft.online.sharepoint.tenantadministration.tenantlog_members(v=office.15).aspx

After playing around it a bit, I was able to retrieve Log messages from my Tenant. This seems to be a preview feature still in development and was not working on all the tenants on which I tested. In fact, it was working only on a newly created Tenant! That too only for the Developer Site.

Having a look at the MSDN docs for the SPO PowerShell cmdlet:
http://technet.microsoft.com/en-us/library/fp161369(v=office.15).aspx

"This function cannot retrieve all SharePoint Online errors. It retrieves a subset of errors that happen due to external systems.
For Beta 2, the only logs available are for Business Connectivity Services (BCS)."

I will keep this post updated with any new information which comes along.

You will need the following DLLs for this code to work:
Microsoft.SharePoint.Client.dll
Microsoft.SharePoint.Client.Runtime.dll
Microsoft.Online.SharePoint.Client.Tenant.dll

The first two assemblies can be found in the ISAPI folder of your SharePoint 2013 Server Box. The Microsoft.Online.SharePoint.Client.Tenant.dll is a part of  the SharePoint Server 2013 Client Components SDK which can downloaded from here: http://www.microsoft.com/en-in/download/details.aspx?id=35585

So without much further ado, here is the code:
And here is the output I got after running the code:


I think the SharePoint team has done a really great job of listening to the community to add new features to SharePoint/Office365 and I am really happy!

Tuesday, March 4, 2014

Create Site Collections with CSOM in SharePoint Online

With the SharePoint Conference 2014, a lot of code samples and articles where recently released. I was most impressed by the Office App Model Samples found here: http://officeams.codeplex.com/

Within that, there is some really good code of which my favorite is Creating Site Collections in SharePoint Online with CSOM. Previously this was only possible via Powershell and the SharePoint Online (SPO) Commandlets. I have modified the code provided in the samples to make it a bit less complex and you can also use it outside of an app e.g. in console applications.

You will need the following DLLs for this code to work:
Microsoft.SharePoint.Client.dll
Microsoft.SharePoint.Client.Runtime.dll
Microsoft.Online.SharePoint.Client.Tenant.dll

The first two assemblies can be found in the ISAPI folder of your SharePoint 2013 Server Box. The Microsoft.Online.SharePoint.Client.Tenant.dll is a part of  the SharePoint Server 2013 Client Components SDK which can downloaded from here: http://www.microsoft.com/en-in/download/details.aspx?id=35585

So without much further ado, here is the code:

Friday, November 29, 2013

Set UserProfile Picture using Client APIs in SharePoint 2013

With the SharePoint 2013 Client APIs, you can only read the User Profile Properties but not modify them. However the only property you can modify is the Current User's profile picture. Source article: http://msdn.microsoft.com/en-us/library/jj920104.aspx

The REST API expects the image to be in the arraybuffer format in order to be set. To convert an image to arraybuffer, we will be using the XMLHttpRequest object

The XMLHttpRequest object allows us to specify the format in which we want the content to be downloaded. The available options are: arraybuffer, blob, json, text, document and some other browser specific formats.

Complete documentation for the XMLHttpRequest object:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest

Also a very good article on how to use the XMLHttpRequest object:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest

A very important point to note is that XMLHttpRequest will work with cross domain images only if the server which is hosting the images allows cross domain requests to be made.

Modern browsers support cross-site requests by implementing the web applications working group's Access Control for Cross-Site Requests standard.  As long as the server is configured to allow requests from your web application's origin, XMLHttpRequest will work.  Otherwise, an INVALID_ACCESS_ERR exception is thrown.

For the sake of simplicity, we will be using the images hosted in the same domain as SharePoint itself so we do not have to worry about cross domain requests.

1) Set Current User's UserProfile Picture using the REST API:




2) Set Current User's UserProfile Picture using the .NET Managed Client Object Model:


This is relatively easy as the SetMyProfilePicture managed method expects the image to be a System.IO.Stream. 

This code assumes you are working with SharePoint Online/Office 365. If you are working with an On-Premise deployment, you do not need to use the SharePointOnlineCredentials class. You can simply create an instance of the NetworkCredentials class for the authentication.

Saturday, October 5, 2013

Knockout.js Simplified

Knockout is a fantastic JS library for data binding and dynamically generating complex HTML. It helps a lot in developing applications which are loosely coupled and where there is minimum dependency between the data and the views.

Before I knew knockout, I used to generate all my repetitive HTML right from my JavaScript file. This had significant disadvantages:
1) Every time I had to change my display code, I had to modify the JavaScript file.
2) The JavaScript file contained the business logic as well as the display logic of my application. This used to make the file very complicated to maintain.
3) If a UI designer had to change the HTML, he would have to consult me in order to look for where to make the changes so that the generated HTML would be according to his requirements.

With knockout, we can keep all the display logic (HTML) in the .html file while all the data logic (and business logic) can be separated in the JavaScript file.

Knockout JS implements the MVVM pattern for developing applications. Now if you are a beginner, all these acronyms like MVC/MVP/MVVM might get confusing. So let me try to explain what exactly is meant by the MVVM pattern.

MVVM stands for Model-View-ViewModel. I know this does not help you at all so let me go in a bit of detail:

Model : Your data. Typically a JSON or XML object which contains data fetched from different data sources like Web Services, SQL Tables, SharePoint Lists etc.

ViewModel: The component which aggregates the data into a format which the View expects. ViewModel also manages combining data from multiple Models. It also handles formatting, sorting, filtering of the data based on custom business logic.

View: HTML Structure which will display data to the user.

Hope that was helpful.

Now lets get into the code right away! We will be looking into a simple example where we will be getting data from an JavaScript Array (Model), filling that data into a ViewModel and then binding that ViewModel to the View (HTML).

Since this article is just introduction to KnockoutJS, I have kept it really simple. I have included the JS code as well as the HTML code in the same file so that it is easier to understand. You will want to separate out the JS code in a different file.

Here is the code:



For more details and tutorials, please see the Knockout.JS documentation which is really nice and detailed: http://knockoutjs.com/documentation/introduction.html

Saturday, July 20, 2013

SharePoint 2013: Get UserProfile Properties with REST API

In my last post about SharePoint 2013 user profile properties, we saw how to get them using the JavaScript Client Object Model. In this post lets have a look at how to get them using the REST API. Here is a quick reference for the REST API endpoints.

(List of All User Properties and UserProfile Properties at the end of the post)


1) Get all properties of current user:

http://siteurl/_api/SP.UserProfiles.PeopleManager/GetMyProperties



2) Get single property of current user:

http://siteurl/_api/SP.UserProfiles.PeopleManager/GetMyProperties/PictureUrl
OR
http://siteurl/_api/SP.UserProfiles.PeopleManager/GetMyProperties?$select=PictureUrl



3) Get Multiple Properties for the current user:

http://siteurl/_api/SP.UserProfiles.PeopleManager/GetMyProperties?$select=PictureUrl,AccountName



4) Get all properties of Specific User:


For Office 365/SharePoint Online:
http://siteurl/_api/SP.UserProfiles.PeopleManager/GetPropertiesFor(accountName=@v)?@v='i:0%23.f|membership|vardhaman@siteurl.onmicrosoft.com'

For SharePoint 2013 On-Premise:
http://siteurl/_api/SP.UserProfiles.PeopleManager/GetPropertiesFor(accountName=@v)?@v='domain\username'



5) Get Specific UserProfile Property of Specific User:


For Office 365/SharePoint Online:
http://siteurl/_api/SP.UserProfiles.PeopleManager/GetUserProfilePropertyFor(accountName=@v,propertyName='LastName')?@v='i:0%23.f|membership|vardhaman@siteurl.onmicrosoft.com'


For SharePoint 2013 On-Premise:
http://siteurl/_api/SP.UserProfiles.PeopleManager/GetUserProfilePropertyFor(accountName=@v,propertyName='LastName')?@v='domain\username'



6) Get Multiple UserProfile Properties for Specific User:


http://siteurl/_api/SP.UserProfiles.PeopleManager/GetUserProfilePropertiesFor
_api/SP.UserProfiles.PeopleManager/GetUserProfilePropertiesFor

As far as my research is concerned, this method is NOT supported in the REST API. The call to this method returns the following error:

"The method GetUserProfilePropertiesFor cannot be invoked as its parameter propertiesForUser is not supported."

If anybody finds any additional information on this, then I would love to update my blog on it. Here is my code for executing the above method:



-------

List of User Properties (Use the GetPropertiesFor function for these):

AccountName
DirectReports
DisplayName
Email
ExtendedManagers
ExtendedReports
IsFollowed
LatestPost
Peers
PersonalUrl
PictureUrl"
Title
UserProfileProperties
UserUrl

List of User Profile Properties (Use the GetUserProfilePropertyFor function for these):

AboutMe
SPS-LastKeywordAdded
AccountName
SPS-Locale
ADGuid
SPS-Location
Assistant
SPS-MasterAccountName
CellPhone
SPS-MemberOf
Department
SPS-MUILanguages
EduExternalSyncState
SPS-MySiteUpgrade
EduOAuthTokenProviders
SPS-O15FirstRunExperience
EduPersonalSiteState
SPS-ObjectExists
EduUserRole
SPS-OWAUrl
Fax
SPS-PastProjects
FirstName
SPS-Peers
HomePhone
SPS-PersonalSiteCapabilities
LastName
SPS-PersonalSiteInstantiationState
Manager
SPS-PhoneticDisplayName
Office
SPS-PhoneticFirstName
PersonalSpace
SPS-PhoneticLastName
PictureURL
SPS-PrivacyActivity
PreferredName
SPS-PrivacyPeople
PublicSiteRedirect
SPS-ProxyAddresses
QuickLinks
SPS-RegionalSettings-FollowWeb
SID
SPS-RegionalSettings-Initialized
SISUserId
SPS-ResourceAccountName
SPS-AdjustHijriDays
SPS-ResourceSID
SPS-AltCalendarType
SPS-Responsibility
SPS-Birthday
SPS-SavedAccountName
SPS-CalendarType
SPS-SavedSID
SPS-ClaimID
SPS-School
SPS-ClaimProviderID
SPS-ShowWeeks
SPS-ClaimProviderType
SPS-SipAddress
SPS-ContentLanguages
SPS-Skills
SPS-DataSource
SPS-SourceObjectDN
SPS-Department
SPS-StatusNotes
SPS-DisplayOrder
SPS-Time24
SPS-DistinguishedName
SPS-TimeZone
SPS-DontSuggestList
SPS-UserPrincipalName
SPS-Dotted-line
SPS-WorkDayEndHour
SPS-EmailOptin
SPS-WorkDayStartHour
SPS-FeedIdentifier
SPS-WorkDays
SPS-FirstDayOfWeek
Title
SPS-FirstWeekOfYear
UserName
SPS-HashTags
UserProfile_GUID
SPS-HireDate
WebSite
SPS-Interests
WorkEmail
SPS-JobTitle
WorkPhone
SPS-LastColleagueAdded

Tuesday, July 16, 2013

Include Caching in jQuery getScript

While going through some MSDN documentation on SharePoint 2013, I noticed that Microsoft has suggested to use the jQuery.getScript method to load the SP.Runtime.js and the SP.js files on the page.
For Example:



I did not think about this twice but when I actually brought this into practice, I noticed that the function was fetching the files every time the page would load. After a bit of digging in the jQuery documentation, I found out that this is because the jQuery.getScript function disables caching. It gets the fresh copy of requested files every time by appending a current time time stamp at the end of the file path. You can see the firebug screen-cap of the call here:


This is not good for us because I don't want to spend extra time getting a fresh copy of the file on every page load. We know that once the file is fetched, the browser caches it and maintains a copy if any further requests for the same file are made in the future. jQuery.getScript by default does not allow us to take the advantage of this feature.

To overcome this limitation. I dug a little deeper into the jQuery docs and found that jQuery.getScript internally calls the good old jQuery.ajax function. This function has a "cache" parameter which we can use to set whether the ajax function looks into the browser cache for the requested file or it directly fetches it from the location. I created a handy function to wrap around the jQuery.ajax call to support caching. Here is the code:



After I run this code, I get the following output in firebug. As you can see, there is no time-stamp at the end of the second request and also the time taken to fetch the file is significantly less (about 90% less) than the call to get the fresh copy.


So as you saw, we have built our own wrapper around the jQuery.ajax function which allows us to get cached files and significantly improve page load times. Hope you find this tip helpful!

Happy JavaScripting!

Batch Operations using the JavaScript Client Object Model

To improve performance and to reduce the time taken for data to travel over the wire, we can do batch operations using the Client Object Model in SharePoint. This can really help in reducing load time of pages and make the user experience better. Batch operations can be done using the .NET as well as the JavaScript Client Object Model. In this post, we are going to focus on how to perform batch operations using the JavaScript Client Object Model. In each of the following operations, only one call from the client to server will be made. It will contain all the information needed to perform the necessary operation. So without further ado, here is the code:

1) Batch Add Items to List:




2) Batch Update Items from List:



3) Batch Delete Items from List:

Now let us analyze what happens behind the scenes when we make one of these batch operations. Here is the firebug screen grab of the call to batch create 5 items:


Now as you can see, only one call is made from the client to the server. It contains all the XML necessary for creating the 5 items. Here is the relevant XML:


Hope you enjoyed this blog post. Happy SharePointing!

Addendum: I would also like to point out one of the hidden gems of the SharePoint world: if you are using Server Side Code (Full Trust), there is a similar batch method available called SPWeb.ProcessBatchData which can be used to bulk add, edit and delete list items. This is really helpful because it can operate on large number of items at once without making repeated calls to the database.