Saturday, January 9, 2010

My Learnings - SharePoint Web Services


In my project, I spent some time on integrating my application with SharePoint. During this, I faced challenges especially with attachments. I am sharing my experience on SharePoint which helps for guys who are new. When you do Google you can find many .NET based solutions to integrate with SharePoint. My application is not .NET based so I have chosen to go with Web Services.
I used XMLHTTP from javascript to send SOAP requests for creating lists, reading and adding attachments to those list items. SharePoint provided Lists web service to achieve my functionality. Even though web services are available I faced challenges in finding  information about web service parameters like listItemID and also during attachment ( attachment support is there only for Custom List category). Here you can find step wise to add an attachment to list Item.

GetListCollection

This web service helps to read all the lists in a site. Using this response you can get List ID, which is GUID and other meta data Information.

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetListCollection xmlns="http://schemas.microsoft.com/sharepoint/soap/">
    </GetListCollection>
  </soap:Body>
</soap:Envelope>

UpdateListItems

This web service helps to create, delete and change list items in a List. Before uploading a document/attachment, list item has to be created. The following request creates a list item called "Learnings".

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <UpdateListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
      <listName>MyLearnings</listName>
      <updates>
        <Batch OnError="Continue" >
          <Method ID="1" Cmd="New">
            <Field Name="Title">Learnings</Field>
          </Method>
        </Batch>
      </updates>
    </UpdateListItems>
  </soap:Body>
</soap:Envelope>

You can find more information about Batch, Method and Field here.

GetListItems


Once list item is added into Custom List, then this method helps to read ID of a list item and also other meta information. Response contains rows ( i.e. list items ) and each row contains ows_ID, which is list Item ID. This is required for adding an attachment. So before adding, this service helps to read ID of a list item.

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
      <listName>MyLearnings</listName>
      <query>
        <Query>
          <Where>
            <Contains>
              <FieldRef Name="Title" />
              <Value Type="Text">Learnings</Value>
            </Contains>
          </Where>
        </Query>
      </query>
      <webid>37bbc01f-0ca2-438b-bb77-7ec23f98a962</webid>
    </GetListItems>
  </soap:Body>
</soap:Envelope>

Here <query> and <webid> are optional parameters. But query helps, when you want to read list items based on some conditions. List's webid value can be retrieved from GetListCollectionResponse, which returns list information in a site.

AddAttachment

This method helps to add attachment to a list item. We have seen how to add a list item and also to get list item ID.  In AddAttachment, list name is name of the custom list ( in our case it is MyLearnings), listItemID is ID of list item and fileName is attachment file. Attachment element contains Base64 encoded content of a file.

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
  <AddAttachment xmlns="http://schemas.microsoft.com/sharepoint/soap/">
    <listName>MyLearnings</listName>
    <listItemID>1</listItemID>
    <fileName>HowtouseSharepoint.doc</fileName>
    <attachment>
    </attachment>
  </AddAttachment>
</soap:Body>
</soap:Envelope>

Using HTML + Javascript it is not possible to read file content directly. So with help of server side program, content has to transfer back to client with Base64 encoding in response to FORM POST. User can add attachment server side also  to avoid content downloading to client. In my case, I have chosen client side as authentication of SharePoint is NTLM ( In .NET delegation support is there. With that, you can do  attachment server side itself. ).
I have written a server side handler to return Base 64 Content.  You can find javascript code below.

I hope this helps for those who are new to SharePoint and trying to do integration with Web Services.

( I used IE's XML DOM API in the following example. )


<html>
<head>

<script type="text/javascript">
function getResponse(url, soapAction, request)
{
var connection = getConnection();
connection.open("POST", url, false);
connection.setRequestHeader("SOAPAction", soapAction);
connection.send(request);
response.value = connection.responseText;
}

function getConnection()
{
if ( window.ActiveXObject )
{
return new ActiveXObject("Microsoft.XMLHTTP");
}
else
{
return new XMLHttpRequest();
}
}


function getListItemsFun()
{
getResponse("<<Site URL>>_vti_bin/Lists.asmx",
"http://schemas.microsoft.com/sharepoint/soap/GetListItems",
GetListItemsReq.XMLDocument.cloneNode(true));
}


function updateListItemFun()
{
getResponse("<<Site URL>>_vti_bin/Lists.asmx",
"http://schemas.microsoft.com/sharepoint/soap/UpdateListItems",
UpdateListReq.XMLDocument.cloneNode(true));
}

function upload()
{
document.getElementById("oForm").setAttribute("target", "uploadFrame");
document.getElementById("oForm").submit();
}

function getListCollectionFun()
{
getResponse("<<Site URL>>_vti_bin/Lists.asmx",
"http://schemas.microsoft.com/sharepoint/soap/GetListCollection",
getListCollectionreq.XMLDocument.cloneNode(true));
}
//this method will be called once uploaded
//encodedResponse is an element in downloaded html which contains Base64 Content.
function upLoadStateChanger()
{

if ( !uploadFrame.document.getElementById("encodedResponse") || ! uploadFrame.document.getElementById("encodedResponse").value ) return;

var attachXml = addAttachMentreq.XMLDocument.cloneNode(true);

attachXml.selectSingleNode(".//attachment").text = uploadFrame.document.getElementById("encodedResponse").value;

getResponse("<<Site URL>>_vti_bin/Lists.asmx",
"http://schemas.microsoft.com/sharepoint/soap/AddAttachment",
attachXml);

}

</script>

<xml id="GetListItemsReq">
<soap:Envelope  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Body>
<GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
 <listName>MyLearnings</listName>
 <query>
<Query>
 <Where>
<Contains>
 <FieldRef Name="Title" />
 <Value Type="Text">Learnings</Value>
</Contains>
 </Where>
</Query>
 </query>
 <webid>37bbc01f-0ca2-438b-bb77-7ec23f98a962</webid>
</GetListItems>
 </soap:Body>
</soap:Envelope>
</xml>
<xml id="getListCollectionreq">
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Body>
<GetListCollection xmlns="http://schemas.microsoft.com/sharepoint/soap/">
</GetListCollection>
 </soap:Body>
</soap:Envelope>
</xml>
<xml id="addAttachMentreq">
<soap:Envelope  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
 <AddAttachment xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>MyLearnings</listName>
<listItemID>1</listItemID>
<fileName>HowtouseSharepoint.doc</fileName>
<attachment>
</attachment>
 </AddAttachment>
</soap:Body>
</soap:Envelope>
</xml>
<xml id="UpdateListReq">
<soap:Envelope  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Body>
<UpdateListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
 <listName>MyLearnings</listName>
 <updates>
<Batch OnError="Continue" >
 <Method ID="1" Cmd="New">
<Field Name="Title">Learnings</Field>
 </Method>
</Batch>
 </updates>
</UpdateListItems>
 </soap:Body>
</soap:Envelope>
</xml>
</head>
<body>
<button onclick="getListItemsFun()">Get List Items</button>

<button onclick="updateListItemFun()">Update List Items</button>
<button onclick="getListCollectionFun()">Get Collection</button>

<form name="oForm" action="<<servlet URL>>" enctype="multipart/form-data" method="POST">
<input type="file" name="file1" id="file1" />
</form>
<input id="but" name="Upload" onclick="upload()" type="button" value="Upload" />
<iframe name="uploadFrame" style="display: none" />
</body>
</html>




No comments:

Post a Comment