Using XMLHTTP to Post Commands in SharePoint Team Services

 

Microsoft Corporation

May 2002

Applies to:
    SharePoint™ Team Services from Microsoft

Summary: XMLHTTP gives an efficient way to the SharePoint Team Services Web developer to post commands to the server. (8 printed pages)

Contents

Introduction
SharePoint Team Services RPC Protocol
CAML Views
Administrative Protocol
ASP

Introduction

XMLHTTP offers the Web developer for SharePoint™ Team Services from Microsoft an efficient way to post commands to the server. It becomes particularly handy when you need to execute commands on the server without leaving the current, calling script block on the client. In the case of several remote procedure call (RPC) methods described in the SharePoint Team Services SDK—for example, ExportList, Display, or RenderView—the server's response comes in the form of XML data that is displayed in the browser; but XMLHTTP and the XML Document Object Model (DOM) offer the ability to work with this data within script. After commands have been posted to the server through the use of an XMLHTTP object, the XML Document Object Model can be used to work with the server's response.

XMLHTTP can be used with native SharePoint Team Services protocols, including the Administrative protocol, the URL protocol, SharePoint Team Services RPC protocol, and the Collaborative Application Markup Language (CAML) Batch Manager. It can also be used to implement Microsoft® Active Server Pages (ASP) in the context of lists. Whichever protocol you are using, you need to perform the following tasks:

  • Construct the string to post, in keeping with the protocol's syntax. If necessary, use the escape characters for the given script language.

  • Create an XMLHTTPRequest or a ServerXMLHTTPRequest object, as well as a DOMDocument object in order to work with the response.

  • Use the XMLHTTP open method to establish a connection with the server.

  • Use the send method to post the command string.

  • Assign the XMLHTTP response to the DOMDocument object for processing.

    Note   The examples in this article assume that you have already installed the Microsoft XML Core Services (MSXML) 4.0, formerly called the Microsoft XML Parser, on the client. Download the Core Services.

SharePoint Team Services RPC Protocol

To post by using the SharePoint Team Services RPC protocol, you can create a simple post form with a text area (PostBody) and assign the appropriate URL to the form's action attribute, such as follows:

<FORM method="POST" action="http://[Server_Name]/[Subweb_Name]/
  _vti_bin/owssvr.dll?Cmd=DisplayPost">
  <TEXTAREA rows="18" name="PostBody" cols="72"></TEXTAREA>
  <INPUT type="submit" value="Submit">
  <INPUT type="reset" value="Reset">
</FORM>

You can then type the RPC command, using the CAML Method, SetList, and SetVar elements, into the form's text area. The DisplayPost command tells the compiler to execute whatever CAML is contained in the post body. In this case, the purpose is to retrieve the data from a custom list, and the following CAML conveys the Display command:

<Method ID="0,Display">
  <SetList Scope="Request">u_[ListName]</SetList>
  <SetVar Name="Cmd">Display</SetVar>
  <SetVar Name="XMLDATA">TRUE</SetVar>
</Method>

When a submit button is clicked, the server returns the data to the browser as XML. However, you might need to integrate this response into a custom application and work with it programmatically in script, and not simply display it as XML.

Instead of creating a post form, you can write a script function that is called when a submit button on the page is clicked. First, construct the string you want to post, such as follows:

<SCRIPT language="JavaScript">
function GetData()
{
   var strPost = "<ows:HttpVDir/>/_vti_bin/owssvr.dll?" +
      "Cmd=DisplayPost&PostBody=<Method ID=\"Data1\">" +
      "<SetList Scope=\"Request\">u_[ListName]</SetList>" +
      "<SetVar Name=\"Cmd\">Display</SetVar>" +
      "<SetVar Name=\"XMLDATA\">TRUE</SetVar></Method>";

Notice that quotation marks have been escaped with "\" for use in JavaScript, and a CAML element (HttpVDir) is used to return the path for the subweb. Next, you can create an XMLHTTP object, open the connection with the server, and then post the above string. You can also create a DOMDocument object to contain the server's response.

   var objDoc = new ActiveXObject("Msxml2.DOMDocument.4.0");
   var objHTTP = new ActiveXObject("Msxml2.XMLHTTP.4.0");
   objHTTP.open("POST", strPost, false);
   objHTTP.send();
   objDoc = objHTTP.responseXML;

In this case, the async parameter has been set to false, which prevents the script from working asynchronously in relation to the server. That is, the script will not continue execution until the server has had the opportunity to process the request and respond. Once the response becomes available, it is assigned to the DOMDocument object. The responseXML property of the XMLHTTP object is used to make this assignment to objDoc, and the XML can then be parsed and data fetched from the appropriate nodes.

   objDoc.setProperty("SelectionLanguage", "XPath");
   var viewNodes = objDoc.documentElement.selectNodes("//*/*/@ows_Price");
   strID = viewNodes.item(2).value;
   alert(strID);
}
</SCRIPT>

Here, the setProperty method specifies that XPath will be the language used in the selectNodes method of the second line, which selects all nodes matching the XPath description, in other words, all ows_Price attributes. The variable strID is assigned the value contained by the second attribute in this collection and a message box displays the return value.

CAML Views

You can use a CAML view within a script block to perform a query on the SharePoint Team Services database and return values for processing. In order for CAML to execute, the page containing the code must include processing directions for the compiler. The <HEAD> section needs to contain the following script block, which allows relative links in the document to work correctly when viewed through the CAML interpreter DLL:

<Script FP_GENERATED="TRUE" Language="JavaScript">
   document.write('<ows:HTMLBase/>');
   var strBinUrl="../_vti_bin/";
</Script>

The <HEAD> section also needs to contain the following block, which allows for processing of the page by the SharePoint Team Services DLL:

<Script FP_GENERATED="TRUE" SRC="../_vti_bin/owsredir.js">
</Script>
<Script FP_GENERATED="TRUE" Language="JavaScript">
   RedirectToFrame("[folder]/[file_name].htm",
   "../_vti_bin/owssvr.dll");
</Script>

A script block containing the following CAML view can also be placed in the <HEAD> section. In this case, the view returns a comma-delimited string of item IDs where stock is less than or equal to 15 for display in a message box.

var strView = "<ows:XML><SetList>u_[ListName]</SetList>" +
   "<View><ViewFields><FieldRef Name="ID"/></ViewFields>" +
   "<ViewBody> <Fields><Field/>" +
   "<HTML><![CDATA[,]]></HTML></Fields></ViewBody>" +
   "<Query><Where><Leq><FieldRef Name="Stock"/>" +
   "<Value Type="Number">15</Value></Leq></Where>" +
   "<OrderBy><FieldRef Name="ID"/></OrderBy></Query></View></ows:XML>";
alert(strView);

This approach works fine when the string doesn't need to be dynamically generated, but when it does need to be generated dynamically—say, when it depends on user input—then a different approach is required. Imagine that the above list name and number in stock are selected through user interaction with a drop-down list for choosing a list and a text box for typing a number. In this case, you need to assign the selected list to one variable (here, selList) and the typed value to another variable (selValue) and then work these variables into the string, as follows:

var strPost = "<ows:XML><SetList>" + selList +
   "</SetList><View><ViewFields><FieldRef Name="ID"/></ViewFields>" +
   "<ViewBody><Fields><Field/><HTML><![CDATA[,]]></HTML></Fields>" +
   "</ViewBody><Query><Where><Leq><FieldRef Name="Stock"/>" +
   "<Value Type="Number">" + selValue + "</Value></Leq></Where>" +
   "<OrderBy><FieldRef Name="ID"/></OrderBy></Query></View></ows:XML>";

However, when a page opens in SharePoint Team Services, the compiler first scans the page for CAML and executes it on the server; then the script is executed on the client. Because you want the CAML to execute in response to script, you need to disguise the CAML from the compiler before you post the string, so that the compiler doesn't immediately attempt to process the CAML when the page is opened and generate an error. To do this, encode the angle brackets ("<" or ">") and quotation marks. Then, before you post to the server through the RPC DisplayPost method, replace the brackets and quotation marks.

The following code illustrates how the above string looks when it's been encoded and prepared for posting. Notice that the XML element has been replaced with the CAML Batch and Method elements (in other words, the CAML Batch Manager is implemented).

var strPost = "<ows:HttpVDir/>/_vti_bin/owssvr.dll?" +
   "Cmd=DisplayPost&PostBody=&lt;ows:Batch&gt;" +
   "&lt;Method ID=&quot;itmIDs1&quot;&gt;&lt;SetList&gt;" + 
   selList + "&lt;/SetList&gt;&lt;View&gt;&lt;ViewFields&gt;" +
   "&lt;FieldRef Name=&quot;ID&quot;/&gt;" +
   "&lt;/ViewFields&gt;&lt;ViewBody&gt;&lt;Fields&gt;&lt;Field/&gt;" +
   "&lt;HTML&gt;&lt;![CDATA[,]]&gt;&lt;/HTML&gt;&lt;/Fields&gt;" +
   "&lt;/ViewBody&gt;&lt;Query&gt;&lt;Where&gt;&lt;Leq&gt;" +
   "&lt;FieldRef Name=&quot;Stock&quot;/&gt;" +
   "&lt;Value Type=&quot;Number&quot;&gt;" + selValue + 
   "&lt;/Value&gt;&lt;/Leq&gt;&lt;/Where&gt;&lt;OrderBy&gt;" +
   "&lt;FieldRef Name=&quot;ID&quot;/&gt;&lt;/OrderBy&gt;" +
   "&lt;/Query&gt;&lt;/View&gt;&lt;/Method&gt;&lt;/ows:Batch&gt;";

Notice that angle brackets for the above HttpVDir element are not encoded, since we want the compiler to immediately return the subweb path for constructing the complete URL. Before posting, the encoding needs to be replaced with angle brackets and quotation marks, such as follows:

var strRep = /&lt;/g;
strPost = strPost.replace(strRep,"<");
strRep = /&gt;/g;
strPost = strPost.replace(strRep,">");
strRep = /&quot;/g;
strPost = strPost.replace(strRep,"\"");

The string can now be posted using XMLHTTP, and the response can be brought into script for processing:

var objDoc = new ActiveXObject("Msxml2.DOMDocument.4.0");
var objHTTP = new ActiveXObject("Msxml2.XMLHTTP.4.0");
objHTTP.open("POST", strPost, false);
objHTTP.send();
objDoc = objHTTP.responseXML;

Administrative Protocol

XMLHTTP can also be used to post Administrative protocol commands, which proves useful in the context of a custom application that administers a Web site based on SharePoint Team Services from outside of SharePoint Team Services. As an example, the following code sample creates and provisions a new SharePoint Team Services subweb, making the POST without leaving the current script block:

var strPost = "http://[server_name]/_vti_bin/_vti_adm/fpadmdll.dll?" +
   "web=/[new_subweb_name]&operation=create&inherit=true&username=" +
   "[domain_name]\\[user_name]&siteprovision=sharepthp";
HTTPobj = new ActiveXObject("Msxml2.XMLHTTP.4.0");
HTTPobj.open("POST", strPost, true);
HTTPobj.send();

Notice that in this case the async parameter has been set to true, meaning that the script will continue execution without waiting for the server's response.

ASP

XMLHTTP can be used to integrate ASP into the functionality of a Web site based on SharePoint Team Services. This may prove useful, for example, when you need to work with data from an external database in the context of a site. To do this, you can create ServerXMLHTTP and DOMDocument objects in a script block on a site page, use these objects to post to an ASP page on the server, and then through script and ASP retrieve the data for further processing in script.

The following sample, which can be added to a site page, makes a POST to a file named BookList.asp and displays the XML data that is returned in a message box.

function GetData()
{
   var objSrvHTTP;
   var objDoc;
   objSrvHTTP = new ActiveXObject("Msxml2.ServerXMLHTTP.4.0");
   objDoc = new ActiveXObject("Msxml2.DOMDocument.4.0");
   objSrvHTTP.open ("POST","http://[Server_Name]/BookList.asp", false);
   objSrvHTTP.send ();
   objDoc = objSrvHTTP.responseXML;
   alert(objDoc.xml);
}

Next, you can use script in the BookList.asp file to create Microsoft ActiveX® Data Objects (ADO) Connection and Recordset objects in order to establish a connection with the database and return its data for processing. This example uses the recordset to construct XML output that is returned to the client.

<%
Dim dbConnection
Dim objDoc
Dim rsBooks
Dim SQL

SQL = "SELECT * FROM BookList"

Set dbConnection = Server.CreateObject("ADODB.Connection")
Set rsBooks = Server.CreateObject("ADODB.Recordset")
dbConnection.open "Provider=Microsoft.Jet.OLEDB.4.0;Data" +
  "Source=[drive:][path]filename.mdb]"
Set rsBooks = dbConnection.Execute(SQL)
Response.ContentType = "text/xml" 
%>
<BookData>
<%
Do Until rsBooks.EOF
%>
  <BkItem>
    <BookID> <%= rsBooks("Book ID") %> </BookID>
    <Title> <%= rsBooks("Title") %> </Title>
    <Writer> <%= rsBooks("Writer") %> </Writer>
    <Stock> <%= rsBooks("Stock") %> </Stock>
    <Price> <%= rsBooks("Price") %> </Price>
  </BkItem>
<%
rsBooks.MoveNext
Loop
%>
</BookData>
<%
rsBooks.close()
dbConnection.close()
%>

In addition to DOM features implemented in the above examples, MSXML offers numerous objects, methods, and properties that can be used in the context of SharePoint Team Services. For more information, see the language reference sections of the Microsoft XML Core Services (MSXML) 4.0.