Tag Archive for REST

My Key Takeaways from #SPC14

WOW is the first word that comes to mind when I’m thinking of the week I have had in Las Vegas during the SharePoint Conference 2014. IT. WAS. AWESOME. It’s also cool to see lots people felt the same way. The hashtag #spc14 was on fire! But still for the people that couldn’t go, I want to point out some new Key Concepts that are going to rock our Dev World!

Office Graph

Something we could have been expecting since MS bought Yammer is a Graph protocol that works with SharePoint, Office and Yammer objects. Yammer was already based on Open Graph (like Facebook is) and therefor it’s no surprise Microsoft has been working on this to cover the entire Office space. In the Keynote the Office Graph was anounced with a demo on Project Oslo. A new, personalized and highly interactive App based on this Office Graph principle. It really looks awesome and the Graph will also be part of a new API in Office! Learn more about this right here: http://blogs.office.com/2014/03/03/work-like-a-network-enterprise-social-and-the-future-of-work/

Unified API’s

With the addition of Office Graph and lots of other new Features, the API’s for Office (I’m including SharePoint as a part of Office) are starting to change. A thin red line that was to discover in the Development tracks this SPC is that Microsoft is unifying the API’s that Office 365 (including SharePoint) have to offer. By that I mean that Microsoft is clearly pushing 1 technique and that is by using REST and OData. Microsoft is heading for a model where every API is a RESTful service, wheter it is an Office API or a SharePoint API. Now this is a big deal! The vision here is that those API’s will be Entity Driven. When asking the API for files they will most likely come from SharePoint or OneDrive. When asking for contacts, they will come from Office. The Office / SharePoint team is now even talking to the Dynamics CRM guys and the goal is to achieve the same for Dynamics CRM Online. That would be sweet!

Examples of the new Office API’s and a list of new Features can be found here: http://officeams.codeplex.com/

The App Model

It may be clear to most of you that considering the API “Unification”, the App Model is still the way to go and is heading for adulthood! Good to hear the Product Team is hoping to get AutoHosted Apps out of Preview by the end of this year. This will be a nice addition to the App Store across the Globe. There already is a roadmap for the localization of the store for the next wave which will be somewhere Q2 of this year. The Netherlands is one of those first countries the App store will become available to.

In combination with the new Office API’s it is way easier to build Office Apps now. Microsoft rebranded these to “Contextual Apps” by the way. On top of this all, Microsoft has released an Open Source Android SDK to build Apps for Android devices. Didn’t see that one coming! You can get it here from GitHub: https://github.com/OfficeDev/Office-365-SDK-for-Android

Another thing that really surprised me was the presence of Google in the App Development tracks. One of my favorite frameworks Angular JS was used quite a lot in App Demo’s. Microsoft is not afraid anymore of Frameworks not build by Microsoft and the MVP’s are really promoting these new JavaScript Frameworks (Angular, KnockOut, Breeze).

Microsoft is opening up

Finally something that I think is the most important thing during these conferences. You can get a good idea of where Microsoft as a company is heading. My overal feeling with Microsoft this conference was that Microsoft is really opening up to it’s partners. Never was I so close to the people that actually built SharePoint and Office 365. As one of the Nordic Partners we had the opportunity to sit down with the productteam and ask questions about the present and future of SharePoint and Office 365.

Besides organizing these kinds of roundtables, it was clear that Microsoft is really happy with the Feedback they receive from everyone in the SharePoint community. There is a User Voice site to submit feedback from a developers perspective. And also Stack Exchange is an official channel used by Microsoft.

http://officespdev.uservoice.com/
http://sharepoint.stackexchange.com/

It was also good to hear that Microsoft is working on plans to re-introduce the Technology Adoption Program (TAP) for Cloud models. This would be a very welcome feature so Partners and Developers can test the new API’s, Features etc that will be released in Office 365 later on. Unfortunately Microsoft is still working on this idea and so my guess is that we will have to wait a little longer before this will come around. Lot’s of uncertainties here, but the important point here is that Microsoft is sharing more and more to it’s partners and developers. Go Microsoft!

Famous last words

When I compare this conference to the one in 2012 I can clearly see Microsoft has started listening to our feedback and they’ve done a great job on this conference. The sessions and speakers where top notch in my experience and everything was very well organized. Obviously I just covered a tiny part of all the stuff that was talked about in the breakout sessions. It’s not clear when all the content will be released, but for now there are lots of Post Conference Blogs you can read to get the information you need.

See you next time at SharePoint Conference!

MVC using Angular and Promises in SharePoint 2013

Lately I’ve been reading all kinds of cool articles about Angular JS. One of them written by Jeremy Thake: http://www.jeremythake.com/2013/10/sharepoint-hosted-app-with-angularjs-for-mvc-javascript/. This was an excellent starting point for me to see what Angular has to offer. I noticed two things:

  1. Scoping in Angular JS is pretty tricky. Jeremy’s example was written in the global namespace and I wanted to add some best practices.
  2. Combine the scoping difficulty with multiple Asynchronous calls from your JavaScript code and it’s easy to get lost. Promises to the Rescue!

Namespaces in JavaScript

A very common issue in coding JavaScript is conflicts between 2 variables with the same name in the global namespace. If you code in multiple JS files it’s possible that var i for instance is used more then once. This can easily be avoided by using Namespaces like this:

var AP = window.AP || {};

This statement loads AP from the global namespace if it already exists and otherwise creates a new namespace AP. The functions or vars created in that namespace will never conflict with same function- or varnames in a different namespace. #winning!

AP.WebPropQuery = function() { var i = 0; };
AP.ContactsQuery = function() { var i = 1; };

This makes the code maintainable and readable while the var i now is always the right value in the right context. If you want to know more this is an excellent read:

http://www.kenneth-truyers.net/2013/04/27/javascript-namespaces-and-modules/

Angular JS

My goal here was to use the namespacing practice with the Angular is written. Angular also has a way of scoping everything and I found challenging to combine it with this approach of Namespaces.

With a directive in the HTML code “ng-app” we specify the scope of this Angular App. Using this code I register it as a Module so I also can use a Service later on.

AP.Promise = angular.module('AP.Promise', []);

My goal in this example is to load a Property from the Web’s Propertybag. This property contains the name of a Contacts list. I want all the contacts to be rendered with Full Name and Email address.

Controllers

A controller in the MVC pattern handles a certain part of the View. In our case a list of Contacts. I used the directive ng-controller=”ContactController” and matching JS code

/*
* Angular Controller Registration
* Dependencies: $scope and the $ProfileService
*/
AP.Promise.controller('ContactController', ['$scope', '$ContactService', function ($scope, $ContactService) {
   $scope.contacts = [];
   $ContactService.getContacts($scope);
}]);

When adding this Controller to the Module, I pass along 2 dependencies. $scope (which is kind of mandatory otherwise the controller would be useless) and $ContactService. In this service the logic is stored for getting the data out of SharePoint. The contents of the service

/*
* Angular Service Registration to Support SharePoint interaction
*/
AP.Promise.service('$ContactService', function () {
//Service Method to Get the Contacts
  this.getContacts = function ($scope) {
     //Logic
  };
});

This is the base of our Angular code. Now we need some JS to get the data out of SharePoint. In this example I’m using the REST API.

REST calls and Promises

One library that makes our lives easier when using REST API is jQuery. You might have noticed that the $ char is very popular and is used by lots of JavaScript libraries. We have to be carefull not to call into the wrong library here.

At the start of this post I created two functions in the AP namespace which we are going to fill. One for the Call to get the Web Property and one for the Call to get the Contacts.

/*
* Query object to retrieve Property from Propertybag
* Return: Promise object that is filled with data after ASync call is returned
*/
AP.WebPropQuery = function ($) {
   var deferred = $.Deferred();
   var execute = function () {
      $.ajax({
         url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/AllProperties?$select=p42contacts",
         method: "GET",
         headers: { "accept": "application/json;odata=verbose" },
         success: function (data) {
            deferred.resolve(data);
         },
         error: function (err) {
            deferred.reject(err);
         }
      });
      return deferred;
   };
   return {
      execute: execute
   }
}(jQuery);

This is what the first function looks like. Now the important part is the Promise var deferred = $.Deferred(); This var is called a promise and is kind of like an object placeholder which you can work with untill the Async call replaces the object with the final result of the call. Using these promises you don’t have to nest the second call in the success function of the $.ajax call. This increase readability and maintainability of your code. Scott Hillier wrote a great piece on Promises and how to use them:
https://curah.microsoft.com/11711/using-promises-patterns-in-sharepoint-2013-apps-with-javascript-and-jquery

Making the function calls

The final missing piece in this is making the function calls from the logic in the Angular Service. Again the code of the service with the missing logic

/*
* Angular Service Registration to Support SharePoint interaction
*/
AP.Promise.service('$ContactService', function () {
   //Service Method to Get the Contacts
   this.getContacts = function ($scope) {
      //First Async Call
      AP.WebPropQuery.execute().promise().then(function (data) {
         //Second Async Call depending on data from 1st call
         AP.ContactsQuery.execute(data.d.p42contacts).promise().then(function (data) {
            //Data to work with
            var results = data.d.results;
            for (var i = 0; i < results.length; i++) {
               $scope.contacts.push({ fullname: results[i].FullName, email: results[i].Email });
            }
            //Apply scope to see results
            $scope.$apply();
         }, function (err) { });
      }, function (err) { });
   };
});

AP.WebPropQuery.execute() is the regular function call. With .promise().then() it now is possible to add a second function call based on the promise that is returned in the first. That second call also returns a promise and with that data we can populate our Model.

The View

The View to match all this JS code is a very plain and simpel piece of HTML.

<script type="text/javascript" src="/Style Library/Scripts/p42.contacts.js"></script>
<div ng-app="AP.Promise">
   <div ng-controller="ContactController">
      <ul>
         <li ng-repeat="contact in contacts">{{contact.fullname}} - {{contact.email}}</li>
      </ul>
   </div>
</div>

Results

The thing I really like about this combination of Promises and Angular is that your JavaScript has very clear build up. It’s very readable and maintainable and on top of that it’s very fast! This way we don’t have to wait on all the SharePoint JS files to be loaded as well since we use the REST API. Very powerfull stuff!

You can download a Visual Studio 2012 Solution here. This solution contains a Sandboxed Solution (still fine for provisioning stuff!) with a default Script Editor WebPart that holds the View HTML with the Angular directives.

Todo yourself:

– Create a Contact List and make sure the Full Name and Email are filled
– Create a Property using SP Designer called “p42contacts” in the rootweb and add the name of the Contact List as value.

SharePoint hosted Apps: Show a Users Presence

On our company Blog I wrote something about User Presence in SharePoint hosted Apps. Check it out: http://blog.point42.nl/post/2013/06/18/SharePoint-hosted-Apps-Show-a-Users-Presence.aspx

Since I joined Point 42 this month I haven’t come to writing anything yet, but here we go with my first Point 42 BlogPost 🙂 A while ago I did some investigation on displaying User Presence from custom JavaScript code. Unfortunately I couldn’t get it working in a SharePoint Hosted App. Now I was able to do some more research and got it working!……

SharePoint 2013: Post a Status Update to a Site Newsfeed (JSOM)

This MSDN Article explains how you’re able to post Newsfeed Items to your Timeline. The Posts however always end up on your Personal Social Feed. How can we post a message to a specific location? For instance a SharePoint Site I follow.

Social Actors

In SharePoint 2013, a SPWeb can also be a Social Actor. This means SharePoint provides some Social Metadata with the Web Object so it’s easy to find and use in a Social Context (even across SiteCollections and/or WebApplications). The Social Actor ID is a unique ID we need.

 

SocialActor Example:
<d:element m:type=”SP.Social.SocialActor”>
  <d:AccountName m:null=”true” /> 
  <d:ActorType m:type=”Edm.Int32″>2</d:ActorType> 
  <d:CanFollow m:type=”Edm.Boolean”>true</d:CanFollow> 
  <d:ContentUri>http://win-6eduurabfig:80/sites/creativecorner/team</d:ContentUri> 
  <d:EmailAddress m:null=”true” /> 
  <d:FollowedContentUri m:null=”true” /> 
 <d:Id>8.a8c7898c48604f3c9dccdc67dbf0805e.014890b080f549e4899619003332b129. a8c7898c48604f3c9dccdc67dbf0805e.0c37852b34d0418e91c62ac25af4be5b</d:Id> 
  <d:ImageUri m:null=”true” /> 
  <d:IsFollowed m:type=”Edm.Boolean”>true</d:IsFollowed> 
  <d:LibraryUri m:null=”true” /> 
  <d:Name>Go Team</d:Name> 
  <d:PersonalSiteUri m:null=”true” /> 
  <d:Status m:type=”Edm.Int32″>0</d:Status> 
  <d:StatusText m:null=”true” /> 
  <d:TagGuid m:type=”Edm.Guid”>00000000-0000-0000-0000-000000000000</d:TagGuid> 
  <d:Title m:null=”true” /> 
  <d:Uri>http://win-6eduurabfig:80/sites/creativecorner/team</d:Uri> 
  </d:element>
 *The ID is without spaces but since it’s really long I broke it up.

Newsfeed

On the Newsfeed page in SharePoint 2013 (Personal Site) we are able to create Updates on the Newsfeed. There is a Dropdown that provides us with the choice Share with Everyone (Post to Social Feed) or with a Site I follow (Post to Site Feed). We can simply use the awesome REST API to get an overview of the Sites I Follow.
“http://win-6eduurabfig:80/_api/social.following/my/Followed(types=4)”
(types=4 means Sites, types=2 means Documents).
Now in order to Post to a Site Feed of one the Sites you follow you just have to pass the SocialActor ID as targetId parameter of the SP.Social.SocialFeedManager.createPost() Method.

 

JSOM Example:
//Check if there is any text
var socialText = “I’d like to share this with you”;
var teamSiteId = “8.a8c7898c48604f3c9dccdc67dbf0805e.014890b080f549e4899619003332b129. a8c7898c48604f3c9dccdc67dbf0805e.0c37852b34d0418e91c62ac25af4be5b“;
//Post the URL to the Personal Newsfeed TimeLine
var clientContext = SP.ClientContext.get_current();
var feedManager = new SP.Social.SocialFeedManager(clientContext);
 // Create the post content.
var postCreationData = new SP.Social.SocialPostCreationData();
postCreationData.set_contentText(socialtext);
// Publish the post.
var resultThread = feedManager.createPost(teamSiteId, postCreationData);
clientContext.executeQueryAsync(function () { //success }, function() { //error });  
Easy as that!

 

Important Sidenotes

1) Some Sites you follow may not have a newsfeed enabled. In this case you will not be able to Post to that Site. You can use this REST Endpoint to check if the Feature for Site Feed is enable on a SPWeb.
 
http://win-6eduurabfig:80/_api/web/features/getById(guid’15a572c6-e545-4d32-897a-bab6f5846e18′)
 
If the Feature is activated this call will return some values. If not the Feature is not activated and it’s not possible to post to this Web.
 
2) The “Sites I Follow” also can contain Sites on which your App is not installed. That means the App is not trusted and doesn’t have permissions to read from that Site. So the Feature check can only be done on Sites that trust your App.

SharePoint 2013 Hosted App Part III

In my Previous posts I created an App that retrieved data from a public website.

SharePoint 2013 Hosted App
SharePoint 2013 Hosted App Part II

I used that data and added it to my App List in SharePoint. In this post I will explain how we also can interact with our personal Timeline using the App Framework. If a song is added to the Playlist, an update is posted on the users Timeline.

App Permissions

All interactions between an App and the App-Host are restricted with certain permissions. These permissions can be set in the AppManifest.xml. A good reference to check which Permissions you’re going to need is MSDN: http://msdn.microsoft.com/en-us/library/fp142383(v=office.15).aspx

To Read and Write from/to the Personal Timeline we need 2 specific permissions in 2 different scopes. Reading from the Timeline needs ‘Read’ permissions with Scope ‘User Profiles’. Writing however needs ‘Write’ permissions with Scope ‘Tenant’.

Schermafbeelding 2012-10-01 om 15.22.59

SP.UserProfiles.js

In order to interact with the Timeline using JavaScript, the library ‘SP.UserProfiles.js’ must be added to the page. The easiest way is to add the ScriptLink tag to the AdditionalPageHead Placeholder.

<SharePoint:ScriptLink ID=”ScriptLink” name=”SP.UserProfiles.js” runat=”server” ondemand=”false” localizable=”false” loadafterui=”true” />

Using the REST interface

Just to show that posting to the users Timeline was successful, the Timeline of the current user is displayed next to the Charts. A persons Timeline can be fetched using the REST interface.

Note: To make this script work on the RTM don’t forget to implement the headers in the $.ajax(); call

var base = getParameterByName(“SPAppWebUrl”);
var url = base + “/_api/social.feed/my/TimelineFeed”;
$.ajax({
url: url,
cache: false,
dataType: “json”,
type: “GET”,

headers: { “ACCEPT”: “application/json;odata=verbose” },
crossDomain: false,
success: function (data) {
var TimeLine = data.d.SocialFeed;
//do databinding
},
error: function (request, status, error) {
console.log(“error: ” + status);
console.log(“incoming Text: ” + error);
}
});

Posting a Status Update

Posting on the Timeline using the JavaScript Client OM is similar to creating an Item in a SharePoint List. I used the following code:

// Initialize the current client context and the SocialFeedManager instance.
clientContext = SP.ClientContext.get_current();
feedManager = new SP.Social.SocialFeedManager(clientContext);

// Create a link to include in the post.
var linkDataItem = new SP.Social.SocialDataItem();
linkDataItem.set_itemType(SP.Social.SocialDataItemType.link);
linkDataItem.set_text(‘sample’);
linkDataItem.set_uri(track.Sample);
var socialDataItems = [linkDataItem];

// Create the post content.
var postCreationData = new SP.Social.SocialPostCreationData();
postCreationData.set_contentText(“I added ” + track.TrackName + ” – ” + track.ArtistName + ” with a {0}.”);
postCreationData.set_contentItems(socialDataItems);

// Publish the post. Pass null for the “targetId” parameter because this is a root post.
resultThread = feedManager.createPost(null, postCreationData);

The SocialDataItem is used to create a link within the Update. After this the only thing that is needed is to ExecuteQueryAsync().

Results

results

In this case Marcel opened the App to add a track to the Playlist. Marcel also follows the administrator and therefor sees updates of administrator in his Timeline too.

This example can be downloaded here