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.
You can download the code here: wsswebservice.js.
Tom | 04-Aug-07 at 7:28 am | Permalink
Can’t download the js file – can you fix pls. thx
glen | 13-Aug-07 at 9:29 pm | Permalink
Oops – sorry. Fixed
Jeroen | 23-Aug-07 at 2:37 pm | Permalink
Great Solution!
I’ll use this for my Vista Sidebar gadget
Cheers,
Jeroen
Boris | 03-Sep-07 at 9:56 am | Permalink
I like your mission! And the script also works super!
Divine | 09-Oct-07 at 9:15 am | Permalink
Can you please explain the point no 2:
“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”
How do u run the javascript from within the sharepoint site?
Calling Sharepoint Webservices from Javascript | 16-Oct-07 at 12:49 am | Permalink
[...] Jump over to his blog. [...]
Shaun | 18-Oct-07 at 1:13 pm | Permalink
I am trying to implement your code however I am getting an error. It’s a soap error and the fault string is:
“Unable to handle request without a valid action parameter. Please supply a valid soap action”
I uploaded the prototype.js file and copied the code from your js file into my page. I am calling the createListItem function from a button. I created a list and updated the list name and the Ajax.Request url. Is there anything else I need to be doing? Thanks in advance!
Apatel | 22-Jan-08 at 9:19 am | Permalink
Getting the same error as above ..“Unable to handle request without a valid action parameter. Please supply a valid soap action”
Do I need to change
“http://schemas.microsoft.com/sharepoint/soap/” to soemthing else since that is not a valid URL?
Apatel | 22-Jan-08 at 2:11 pm | Permalink
Where in the code do you specify the SOAPAction? Is that what causes the error “Unable to handle request without a valid action parameter. Please supply a valid soap action.”
Jason Kuter | 29-Jan-08 at 8:12 am | Permalink
You can do NTLM authentication in Firefox pretty easily. See:
http://www.testingreflections.com/node/view/1365
Peyton King | 21-Aug-08 at 11:35 am | Permalink
This looks great and I am about to try it; previous attempts at using JavaScript to call web services have been impossible.
My question is, is there any setting that needs to be thrown on the SharePoint site to allow web services to be called? I keep hitting a wall trying to do this, and if I know how they have shut it off, I could force the issue.
Now the ops guys just say, no idea, SharePoint web services?
Also the site is an https site, but since I am running these from a page in the same SharePoint site and am fully logged in as an accredited user, I would not think it an issue.
Thanks,
Peyton
glenc | 21-Aug-08 at 11:46 am | Permalink
Peyton – there’s nothing you should need to do on the SharePoint side. The SharePoint web services are enabled and available by default. In fact, I believe that’s how Office integration works. Https should not be a problem either.
Peyton King | 21-Aug-08 at 2:02 pm | Permalink
Changed server, site and my list…
Seems to be bombing out on the
It never makes it to 3…
Anything need to be changed in the Soap up top?
I am executing this out of a CEWP on an onclick event; the CEWP is on the same page as the list, but I do not think that matters…
Thanks again,
Peyton
glenc | 21-Aug-08 at 2:06 pm | Permalink
What is happening? Are you getting an error message?
Peyton King | 21-Aug-08 at 2:08 pm | Permalink
CODE NOT EXECUTING SUCCESSFULLY…
‘
var soap = Soap.createEnvelope(
“UpdateListItems”,
“http://schemas.microsoft.com/sharepoint/soap/”,
parameters);
‘
Peyton King | 21-Aug-08 at 2:11 pm | Permalink
I am getting a standard JS error…
Object expected…
I tracked the line down by using an alert prior and after…
My guess is I have the SOAP mucked up with a line break that should not be there…
glenc | 21-Aug-08 at 2:18 pm | Permalink
You probably want to make sure all of the XML and things like that are on the same line. I’ve broken them apart to make it easier to read in the blog post. Try downloading the http://files.glenc.net/articles/wsswebservice/wsswebservices.js file to check the real syntax.
Peyton King | 21-Aug-08 at 2:38 pm | Permalink
Good idea, and I started with that to avoid the line issues, but I pulled it down again and replaced the soap section…
Since it is the char 17, I think the createEnvelope is not working…
Does there need to be an AJAX file somewhere (I know, no SOAP and no AJAX does make a clean developer)?
So I am thinking that the JS is not finding that function…
Thanks again, you know it is a real pleasure to meet someone who has at least made this work somewhere, and your words about SharePoint at the top could not be more true…
However, I have noticed that I do not have any Prototype Javascript library.
Is there a way to do this without that as I am not going to be able to install anything here.
But I can use any Javascript or anything else in CEWP.
glenc | 21-Aug-08 at 2:41 pm | Permalink
That’s the issue – you need Prototype. You can just upload prototype to a document library though if you don’t have server-side access. That way you can reference it from the CEWP.
Peyton King | 21-Aug-08 at 2:42 pm | Permalink
I can dump a whole javascript library into a CEWP or call it externally and often do, but where would an AJAX library go relative to SharePoint as I can’t believe that it would have to go onto every work station…
thanks,
Peyton
Peyton King | 21-Aug-08 at 2:44 pm | Permalink
Hmmm, document library on same site, or would a higher level work, and do I need to get the source from this gitmo place?
I can frop into a document library fine…
And how would I reference the code?
Peyton King | 21-Aug-08 at 3:03 pm | Permalink
But there is theoretically a way to do this without the library…
thanks again for all your help…
Peyton
glenc | 21-Aug-08 at 5:34 pm | Permalink
The prototype javascript library is the only dependency. It contains all functionality needed to make Ajax calls. In fact, you could completely do away with Prototype if you wanted to write your own XMLHTTP requests. Prototype is just a convenience.
You can upload prototype to any document library anywhere and then reference it in a CEWP like this:
<script language=”javascript” src=”http://path/to/my/prototype.js” ></script>
glenc | 21-Aug-08 at 5:36 pm | Permalink
Actually you could even reference it at google and not even worry about downloading it:
<script src=”http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js”></script>
Catalin’s Zeroes and Ones » Blog Archive » Calling SharePoint web services using jQuery | 02-Oct-08 at 2:57 am | Permalink
[...] to update a SharePoint list item directly on client side in a classic SharePoint list form. I found this blog who explains very well how to do it by using Prototype but I was already using jQuery and [...]
lyntonS | 06-Oct-08 at 5:41 am | Permalink
I would like to know how you would call a web service to return the items displayed in a list to be comsumed by the Silverlight APP:
http://www.codeplex.com/SlideShow
It currently only uses a data.xml file which is static and therefore of not very extendable? Any clues?
Kevina | 28-Oct-08 at 7:52 am | Permalink
People should read this.
Myron | 03-Dec-08 at 9:45 am | Permalink
This is great example, but what if you want to execute outside sharepoint? How can the code pass credentials?
Any hints would be more than welcome. TIA!
cepa | 08-Apr-09 at 3:00 am | Permalink
your link is dead
Matt Call | 15-Nov-09 at 4:10 am | Permalink
Thank you for this very useful article. But I had difficult time navigating around your site because I kept getting 502 bad gateway error. Just thought to let you know.