SharePoint 2010 and AJAX – Part 1

I decided to write some tips about building a complete AJAX solution running on SharePoint 2010. There is no rocket science here but sometimes it’s not so simple to put all the pieces together to make a robust and easy to maintain solution. This post will give you some recipes to build AJAX components based on a layer architecture.

This first part deals about setting up your solution and deploy required clients libraries on your SharePoint environment.

Creating the projects

Create a new empty SharePoint project, choose a SharePoint site to deploy your solution and select the “Deploy as farm solution” option. Now add the following folders:

  • Helpers
  • Entities
  • BL
  • Services
  • WebControls

You should obtain something like this :

Adding jQuery

I can’t work anymore without jQuery. It’s a very powerful way to traverse and manipulate the DOM of your page furtermore it provides AJAX helpers. SharePoint does not include jQuery so we have to add it to our solution and ensure that it will be available everywhere in our SharePoint site.

There are multiple solutions to this problem, the one I prefer is to use the delegate control AdditionalPageHead to register our scripts.

First thing to do is download the latest release of jQuery. So, go to http://jquery.com/  and grab the latest production (or development) version.

Then add the SharePoint mapped folder “Layouts” to your project. Visual Studio will add a folder with the name of your solution into it. Add another folder “Scripts” inside and save your version of jQuery here.
Thanks to that jQuery will be deployed into the SharePoint’s hive folder.

Now we will use a WebControl to register the script into the pages. In your project, add a new class named “AdditionalPageHead.cs” into the WebControls folder. Then make the class public and inherit from System.Web.UI.UserControl.

 

In this WebControl you can register the jQuery file thanks to the ClientScriptManager of the page. This can be implemented like this :

I use the SPUtility.MakeBrowserCacheSafeLayoutsUrl in order to generate a URL that won’t be cached by the browser. It just adds a hash in the URL of the file (in a query string).

Now we have to use a Element file to register our Delegate Control. So let’s add a SharePoint Module named “AdditionalPageHead” to our project, delete the sample file of the module and edit the Element file :

Don’t forget to update the ControlAssembly value and ControlClass with your own namespace and public key token.

Now rename the feature, I chose “WebControls” and set the scope to “Site”. Ensure that the AdditionalPageHead module is included into the feature:

feature

We have a last thing to do in order to make this control work properly : add a Safe Control Entry. Opens the properties of the AdditionalPageHead module (right-click on it) and edit the “Safe Control Entries” attribute :

safecontrols

Now deploy the project to your test environment and you should see jQuery loaded into the Developer Toolbar of Internet Explorer :

devtoolbar

Note : instead of creating a class inheriting from UserControl you can add a User Control directly from the Add new item window of Visual Studio. This will create an ASCX file and the code-behind. The benefit of this method is that you don’t have to add the Safe Control Entry. It’s up to you.

Adding Knockout.js

The main problem when you build an AJAX control is to bind the data with the UI. Server-side we have a lot of controls to do such a thing : Repeater, DataList, GridView… Client side is an other story, it can be such a pain to create controls dynamically and bind data to them. Knockout solves this problem by applying the MVVM pattern in JavaScript. It enables you to declare templates and bind them to your data. Your UI  can be automatically refreshed when the View Model changes. Through this article I’ll try to explain the basics of Knockout but I strongly suggest you reading the official documentation if you want to go further : http://knockoutjs.com/

Start by downloading the last version of Knockout and the Knockout Mapping plugin and add them to the Layouts/Scripts folder we created before. Then add a RegisterClientScriptInclude call into the AdditionalPageHead UserControl to register the script files :

Redeploy the project and check if the knockout.js file is loaded.

Creating the Entity and the Business Layer

I’ll take a very simple example for the business layer. We will return the items of a SharePoint Tasks list. This is not very useful but accessing the data is not the point of this article so I let you adapt the code to your needs. You can query items on a list, search results or even data stored into an external database, this won’t change the rest of the solution.

Creating the Entity “Task”

Start by adding a class “Tasks” into the Entities folder and add some basic fields and constructors :

Two important things here :
– You must apply the DataContract to the Task Entity because it will be serialized / deserialized by the DataContractSeralizer when sending and receiving messages through the WCF Service.
– You must apply the DataMember attribute to each field of the Task Entity you want to serialized.

You noticed that I added an enumeration to store the value of the task’s status. I put this enumeration in the same file that the Task class.
When a Task will be instantiated from an SPListItem we will have to convert the SPFieldChoiceValue to a TaskStatus enumeration. In order to achieve this conversion I use a custom class : ChoiceFieldValueAttribute. You can find all the explanations on my blog : SharePoint Choice Field, CAML and Enum.

Here I’ll just give you the steps to add it to our project. Add a new class “ChoiceFieldValueAttribute” into the Entities folder and copy the following lines of code :

Creating the TaskManager

Now we have to create a class to retrieve the data from SharePoint. Add a class “TasksManager” to the BL folder :

I won’t explain this piece of code because there is nothing special here about creating an AJAX component, it’s not rocket science. You can implement your business layer as you want. I often use LinQ to SharePoint to retrieve strongly-typed entities but in this example I’ve decided to get these with the classic SharePoint Object Model and CAML.

All you need is a method GetTasks returning all the tasks of a SharePoint list and a AddTask method to create new items in this list. All the other stuff deals about the disposal mecanism.

Creating the WCF Service

Here is the tricky part if you never have created a WCF Service hosted in SharePoint. It’s pretty easy actually because SharePoint handles all the configuration itself (you don’t have to specify endpoints and all of these XML stuffs).

The WCF Service Contract

Let’s begin by adding an interface “ITasksService” in the Service folder of our project. This interface will define the contract of the WCF Service.

  • ServiceContract : specifies that this interface is a Service Contract.
  • ServiceKnownType : add this attribute for each type that may be serialized / deserialized when a Service method is called. In this example we are only working with Task entities so this is the only type to define.
  • OperationContract : add this attribute on each service method.
  • WebInvoke : this attribute specifies that the decorated method can be called in REST. Moreover you can configure if the method should be called with a POST or GET request.

The Service Implementation

Now we have to implement our contract. Add a “TasksService” class into the “Services” folder and implement the ITasksService interface.

  • BasicHttpBindingServiceMetadataExchangeEndpoint : tells to SharePoint to enable a MEX endpoint

The SVC file

The last step is to create the svc file that will define our service’s type and which SharePoint service factory to use.
The svc file must be deployed to the SharePoint ISAPI folder, right-click on your project è Add è SharePoint Mapped Folder and choose the ISAPI folder. Then add a file named “TasksService.svc” into this folder. The file type does not matter, it can be an empty text file.
Add the following content :

The service attribute must sepcify our service implementation. Replace my assembly full name by yours. Usually you can use the token $SharePoint.Project.AssemblyFullName$ that should be replaced by Visual Studio when packaging your project. In my case it didn’t work on this project so I just put my assembly full name myself.
The factory can be one of the following SharePoint Factories :

  • MultipleBaseAddressBasicHttpBindingServiceHostFactory = SOAP service
  • MultipleBaseAddressWebServiceHostFactory = REST service
  • MultipleBaseAddressDataServiceHostFactory = ADO .Net Data Service

Since jQuery works well with REST  services we choose the second one.

Creating the WebPart

The last step is about creating the WebPart which will consume our WCF Service. I’m suggesting you to first create a very basic WebPart calling the Service without displaying anything. You should be able to see thanks to a tool like Fiddler if the service is actually returning the data. Then you add the databinding with knockout.js.

Adding the WebPart

Add a new Visual WebPart “TasksWebPart” into the WebControls folder of the project and ensure that the WebPart belongs the WebControl feature. Then add the following content into the ASCX file of the WebPart :

This piece of code will enable you to test your service. Deploy the project to a SharePoint development environment and add the WebPart in a page. The WebPart should display the list of your tasks :

demo1

If you start fiddler you can explore the result of the AJAX Call thanks to the JSON inspector. If you don’t have installed Fiddler already I suggest you to do it right now. This tool is essential to debug this sort of components. It enables you to see in details the HTTP requests made by Internet Explorer and to inspect the answers of SharePoint.

fiddler

In the bottom right section of this screenshot of fiddler, you can see the result as JSON. You will notice that the result is always wrapped into an object which name is the concatenation of the service method and the constant “Result”.

DataBinding with Knockout.js

If you have never worked with Knockout.js before I suggest you to read the official documentation here : http://knockoutjs.com/documentation/introduction.html
The three points : Observables, Computed Observables and Observable Arrays are the main concepts to begin with this framework.

There are multiple ways to create the View Model which will be used by Knockout. First the entities returned by the WCF Service can be stored either into a native JavaScript array either in an observable array. The last one is useful when refreshing the View Model. If you want to refresh the WebPart without a postback by making another call to the WCF Service, it is very easy to refresh the whole view thanks to an observable array. Moreover if you support adding new items directly within the WebPart it will make the work straightforward.
Then each field of the entities can be converted to observables. It can be useful if the entities themselves are refreshed.

For this example we will use the most powerful and flexible solution : an observable array of observable entities (not a suprise isn’t it?).

Using the mapping plugin

The WCF service returns JSON objects that must be converted into observable objects. We can do this manually by assigning each field into observables or use the Mapping plugin of Knockout which has been added in the “Adding Knockout.js” part of this article.

First of all we need to add a field into our TasksManager to store the data. Add a “tasks” field into the constructor :

We use Knockout to create an empty observable array and assign it to the new field.
Then we need to convert the JSON objects into observables. Update the for loop in the getDataSucceeded callback function :

The fromJS function of the Knockout Mapping plugin enables to convert the JSON into observables. Note that the converted objects are not observables themselves, only their fields are now observables. So you can’t databind the View on a Task for example but you can do it on a Task’s Title field.
By doing this we bind our Model to the View Model.

Here you can see the content of the mapped object when debuging with the developer tools of Internet Explorer :

knockoutmapping

Note : To access to the Id field’s value we would write : task.Id() and not task.Id given that this field is an observable.

Creating the view

Replace the div with the id “TasksContainer” by this one and its content :

Then update the constructor of TasksManager :

Only the last line has been added to this constructor. The applyBindings function is like the “DataBind” method in .Net. It binds your View Model to the View.
The first argument is very important : it’s the View Model. And yes we are using the whole TasksManager object as the View Model.

So when we specify the token “tasks” into the “foreach” binding in the div element, we are refering to the “tasks” field of the TasksManager object.
The “Title()” token refers to the “Title” field of the current data item iterated by the foreach.

The second argument enables you to use multiple Views and View Models on the same page. If you don’t specify a DOM element when calling applyBindings, Knockout tries to bind the specified View Model at the page level. This doesn’t work if you have multiple views.
That’s why we target on which view the View Model is bound thanks to this second argument.

Deploy the changes and you should see your tasks.

Refreshing the data

Ok that’s fine but nothing new here. We can also get the list of tasks without Knockout and all this View Model stuff. That’s true but remember that in the first example we just write a list of Tasks. In a real-world example you will need to display plenty of data and add some events and behaviors. To illustrate how knockout can make your developer life easy, we will add a button to refresh our view model.

Modify the HTML markup to add an outer container around the existing one and a button, then updates the ID attributes :

Now we need to bind the View Model to the outer container “TasksWebPartContainer” instead the “TasksContainer” we just delete :

That’s all we need to refresh our data. If a new item is added to the SharePoint list, the WCF service will return it and thanks to the “tasks” observable array, the new results will be displayed with the new item. It is the same thing if an existing tasks is modified.

Next…

As you can see in this post’s title, you are reading the first part of a post series about AJAX and SharePoint. So stay tuned if you want more about generating dynamic client options for your AJAX components and some other tips.

Update : you can now read the next part of this article here:

SharePoint 2010 and AJAX – Part 2

Download

Here is the code of this demo :

WawawumAjaxPatterns.zip