Sharepoint 2007

November 23, 2010

SharePoint 2010 Client Object Models – The ECMAScript library

Filed under: SharePoint 2010 — canoosh @ 6:40 pm

SharePoint 2010  ships with 3 new object models:

  1. A managed .NET API for building client applications using a SharePoint object model.
  2. A managed Silverlight object model.
  3. An object model to be used in Javascript, the ECMAScript library.

For developers this is an important step forward. Until now, developing SharePoint applications using an object model was limited to applications running on the server. For client applications we had to rely on web services and the RPC protocols. Using these 3 new models, it will be much easier to create client applications. And the reach of our applications will be bigger, because they are very likely to also run on the new SharePoint Online. The three object models are a limited sub set of the server object model. Most objects, properties and methods of the site collection (SPSite) and it’s underlying structures are available in the new models.

In this article I will show you an example of a custom ASPX page that will use the Javascript library. It is a page that runs in the LAYOUTS folder. It shows all users that have direct permissions on the current site. By clicking a user name, the page will show me more information about that user. By selecting a user and one of the available SharePoint groups, the page will add the user to that group. After doing that, the page will remove the permissions for the user.

Step 1 – Show the users and groups

The ASPX page loads the lists with users and groups in the OnLoad of the page. It creates a collection of custom objects and sets these collections as the datasource for the Repeater controls. The code snippet below shows how the users are loaded:

   1: SPWeb web = SPContext.Current.Web;
   2: List<SharePointUser> users = new List<SharePointUser>();
   3: foreach (SPRoleAssignment assignment in web.RoleAssignments)
   4: {
   5:     if (assignment.Member is SPUser)
   6:     {
   7:         SPUser user = (SPUser)assignment.Member;
   8:         SharePointUser usr = new SharePointUser(user.ID, user.Name);
   9:         users.Add(usr);
  10:     }
  11: }
  12: listUsers.DataSource = users;
  13: listUsers.DataBind();
The snippet below shows the ASPX code for the repeater that shows the users:
 1: <asp:Repeater ID="listUsers" runat="server">
   2:     <HeaderTemplate>
   3:     <h3>Users with direct permissions on this site</h3>
   4:     </HeaderTemplate>
   5:     <ItemTemplate>
   6:     <li style="list-style-type:none">
   7:         <input type="checkbox" id="selectUser<%# DataBinder.Eval(Container.DataItem, "ID") %>" name="selectUser" />
   8:         <a href="javascript:getUserInfo(<%# DataBinder.Eval(Container.DataItem, "ID") %>);">
   9:             < %# DataBinder.Eval(Container.DataItem, "Name") %>
  10:         </a>
  11:     </li>
  12:     </ItemTemplate>
  13: </asp:Repeater>

Step 2 – Preparing the page for using the ECMAScript library

The ECMAScript library is available in a number of JS files in the LAYOUTS folder. The main file is SP.js.
When you include this file in the APSX page using a ScriptLink control,
 all other required JS files are loaded automatically. This MSDN page shows all relevant files.
By linking SP.js to your page, the SP namespace is registered. This is the SharePoint namespace that contains
all objects. If you are going to build code using this library, you will very likely need this MSDN Page to
reference what object, properties and methods are available. The SharePoint js files are minified
(‘crunched’ in the SDK) versions. This makes them hard to read and use for debugging.
Therefore every js file also has a ‘debug’ equivalent in the same folder. By opening sp.debug.js
 you will be able to see what is available in the SP namespace.

The snippet below show how to prepare the ASPX page:
   1: <SharePoint:ScriptLink
   2:     Name="sp.js" LoadAfterUI="true" Localizable="false"
   3:     runat="server" ID="ScriptLink1" />

Step 3 – Getting the user information

As we have seen in step 1, clicking a user’s name fires the javascript function ‘selectUser’.
This function is shown in the snippet below.

   1: function getUserInfo(userID) {
   2:     var clientContext = new SP.ClientContext.get_current();
   3:     var web = clientContext.get_web();
   4:     var userInfoList = web.get_siteUserInfoList();
   5:     var camlQuery = new SP.CamlQuery();
   6:     camlQuery.set_viewXml('<View><Query><Where><Eq><FieldRef Name=\'ID\'/>' +
   7:                           '<Value Type=\'Number\'>' + userID + '</Value></Eq>' +
   8:                           '</Where></Query><RowLimit>1</RowLimit></View>');
   9:     this.collListItem = userInfoList.getItems(camlQuery);
  10:     clientContext.load(collListItem);
  11:     clientContext.executeQueryAsync(
  12:         Function.createDelegate(this, this.onQuerySucceeded),
  13:         Function.createDelegate(this, this.onQueryFailed));
  14: }

As in server side code, we first need to get the SharePoint context. Because our page is an ASPX page running

in the LAYOUTS folder, it is always in context of the current SharePoint site. In all 3 new client object models,

the SharePoint context is represented in a ClientContext object. In line 2 of the snippet above, we’re getting the

current SharePoint context. The next few lines look pretty familiar if you are used to SharePoint server side

programming. We are getting a reference to the User Information List of the current site. Next we create a CAML

query to find the list item for the user that was selected, and we load the items based on that query from the list.

The big difference with the server side object model, is that we did not yet have any contact with SharePoint.

Although we have called the getItems method of the list, our collection is not yet loaded.

This happens when we load the collection in line 10 and execute the query using clientContext.ExecuteQuery in line 11.

This gives you the option to minimize the number of roundtrips to the server from your client code.

This makes SharePoint client programming different from server side programming.

You need to do more thinking about what objects and properties to use when.

It makes sense to load as many objects you need, before calling ExecuteQuery once,

to actually get the objects from the server.

In the sample above, you see another difference between client and server side programming.

The ECMAScript library is, as the Silverlight API, asynchronous. The ExecuteQuery method takes 2 parameter,

the functions that will be called in both a success and a failure scenario.

The snippet below shows the ´success´ function of my sample page:

   1: function onQuerySucceeded(sender, args) {
   2:     var item = collListItem.itemAt(0);
   3:     var profile = item.get_item('Notes');
   4:     var pictureUrl = item.get_item('Picture').get_url();
   5:
   6:     var userImage = document.getElementById('userImage');
   7:     userImage.src = pictureUrl;
   8:     var profileDiv = document.getElementById('userProfile');
   9:     profileDiv.innerHTML = profile;
  10: }

This code loads the first item from the collection, get the values of the Notes and Picture

Step 4 – Move the user to the group

Last part of this article show how to remove the user permissions and add the user to the selected group.

When a groupname is clicked, the javascript function moveSelectedUsersToGroup is called and the ID of the group

is passed as parameter. The snippet below shows this function:

   1: function moveSelectedUsersToGroup(groupID) {
   2:     var users = document.getElementsByName('selectUser');
   3:     this.clientContext = new SP.ClientContext.get_current();
   4:     this.web = clientContext.get_web();
   5:     var groups = web.get_siteGroups();
   6:     var group = groups.getById(groupID);
   7:     var groupUsers = group.get_users();
   8:     for (i = 0; i < users.length; i++) {
   9:         if (users[i].checked) {
  10:             var id = users[i].id.replace(/selectUser/, '');
  11:             var siteUsers = web.get_siteUsers();
  12:             var user = siteUsers.getById(id);
  13:             groupUsers.addUser(user);
  14:             var assignments = web.get_roleAssignments();
  15:             var assignment = assignments.getByPrincipalId(id);
  16:             assignment.deleteObject();
  17:             clientContext.executeQueryAsync(
  18:                 Function.createDelegate(this, this.addUsersSucceeded),
  19:                 Function.createDelegate(this, this.onQueryFailed));
  20:         }
  21:     }
  22: }

What this does before the query is executed to SharePoint, is:

  • get a reference to the SharePoint group
  • find the selected user in the site users
  • add the user to the selected group
  • find the role assignment for the selected user
  • delete the role assignment for the selected user

By submitting the query to SharePoint, all these actions are all executed at once in 1 roundtrip to the server.

If this action is successful, the javascript function addUsersSucceeded is called.

This function has not specical function, it notifies the user about the outcome of the process.

In this article we have seen how to use one of the three new client object models, the ECMAScript library.

Although programming client applications is now a lot easier, and is more like programming the server,

the are some conceptual differences that are important to understand.

Advertisements

Create a free website or blog at WordPress.com.