posted by 준치 2008. 9. 26. 23:13


Calling SharePoint Web Services from Javascript

I’m on a mission. And that mission is to build SharePoint apps without dropping code on the server. Why would anyone want to do this? Well, in many enterprise or hosted environments you don’t have the ability to drop DLLs into a shared SharePoint environment. This has often limited the types of applications we can build to out of the box features or SharePoint designer. But with some Javascript and the WSS web services, we can build a more complex app all with AJAXy goodness.

This code sample uses the Prototype Javascript library. When you see Ajax.Request, that’s using prototype’s Ajax framework. The great thing about prototype is that everything is cross-browser compatible.

First we need some code that formats a simple SOAP envelope. SOAP is the required protocol for communicating with the SharePoint web service.


var Soap = {
  createEnvelope: function(action, ns, parameters)
  {
    var soap = '<?xml version="1.0" encoding="utf-8"?>
        <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
        <soap12:Body>';
    soap += '<' + action + ' xmlns="' + ns + '">';
    soap += Soap.__parseParameters(parameters);
    soap += '</' + action + '></soap12:Body></soap12:Envelope>';
    return soap;
  },

  __parseParameters: function(parameters)
  {
    var params = "";
    if (typeof parameters == 'object')
    {
      // check if we were provided an array or an object
      if (typeof parameters.push == 'function')
      {
        for (var i = 0, length = parameters.length; i < length; i += 2)
        {
          params += "<" + parameters[i] + “>” + parameters[i+1] +
              “</” + parameters[i] + “>”;
        }
      }
      else
      {
        $H(parameters).each(
          function(pair)
          {
            params += “<” + pair.key + “>” + pair.value + “</” + pair.key + “>”;
          });
      }
    }
    return params;
  }
}
Okay, so now we can make a SOAP envelope as simple as this:

var mySoap = Soap.createEnvelope(
  "MyAction",
  "http://schemas.microsoft.com/sharepoint/soap/",
  { param1: "value", param2: "value" });
Simple enough. Now let’s call a SharePoint web service. We’ll use the Lists web service and create a new list item. The UpdateListItems method allows us to pass in some XML defining the items to create. So first I’m going to build that XML.

var batch = '
  <Batch OnError="Continue">
    <Method ID="1" Cmd="New">
      <Field Name="ID">New</Field>
      <Field Name="Title">Hello World</Field>
    </Method>
  </Batch>';
Next we’ll call the web service using the Ajax.Request object:

// build parameter object
var parameters =
{
  listName: "My List",
  updates: batch       // xml created earlier
}

// create soap envelope
var soap = Soap.createEnvelope(
  "UpdateListItems",
  "http://schemas.microsoft.com/sharepoint/soap/",
  parameters);

// call web service
new Ajax.Request(
  "http://myserver/mysite/_vti_bin/lists.asmx",
  {
    method: "post",
    contentType: "application/soap+xml",
    postBody: soap,
    onSuccess: function(transoprt) { alert("Success: " + transport.responseText); },
    onFailure: function(transport) { alert("Error: " + transport.responseText); }
  });
If all goes according to plan, I should have a new list item with the title of “Hello World” in the list called “My List”.

A couple of points about the javascript above:

It’s certainly not the greatest Javascript in the world. I plan to clean it up and hopefully release a Javascript library for working with all of SharePoint’s web services.
The user’s browser must already be authenticated for this to work. Prototype doesn’t have a way to pass credentials to the web service so make sure you run this from a machine joined to the same domain as the sharepoint site. Ideally this is running within a sharepoint site so that should take care of the authentication problem.
FireFox has an issue because it doesn’t pass domain credentials automatically. This makes debugging hard from your workstation, but if it’s running on a SharePoint site where the user has already authenticated, it works fine.
I cheat in the example above and break strings onto multiple lines. That’s for the purpose of formatting only. If you copy and paste this code directly it won’t work.