You can retrieve XML data from Exchange in a number of ways. We looked at one way ”using XML Web services ”in Chapter 14. Another approach uses the WebDAV protocol. WebDAV is an extension to HTTP, which specifies how to perform file processing. Using WebDAV commands, you can lock a resource, get a property, or change a property, and because WebDAV is an HTTP extension, it can even work through firewalls and proxy servers.
You might be wondering how to use a protocol such as WebDAV within your Web applications. Microsoft Internet Explorer 5.0 and later ship with a component called XMLHTTP for working with the WebDAV protocol. In Internet Explorer 6.0, this component is part of the Microsoft XML Core Services (MSXML). If you use Internet Explorer 6.0, be sure to get the most recent patches as outlined in Microsoft Security Bulletin MS02-008.
With the XMLHTTP component (shown in Figure 16-1), you must still send correctly formatted WebDAV requests . However, the XMLHTTP component simplifies this. You should use this component only on the client side because that's the environment it was built for. If you're writing code on the Exchange server, you should write to the server version of XMLHTTP (called ServerXMLHTTP), Collaboration Data Objects for Exchange (CDOEX), or ActiveX Data Objects (ADO).
We'll look at the most important properties and methods of the XMLHTTP component so you can use them in your client applications. These properties and methods are Abort , OnReadyStateChange , Open , ReadyState , responseBody , responseStream , responseText , responseXML , Send , SetRequestHeader , Status , and StatusText . All other properties and methods of XMLHTTP are fully documented by Microsoft Developer Network (MSDN) at http://msdn.microsoft.com .
The first method you'll probably use with the XMLHTTP component is the Open method. This method takes five parameters: Method , URL , Async , User , and Password . The Method parameter specifies which HTTP method to use, such as GET , POST , PROPPATH , or SEARCH . The URL parameter represents the absolute Uniform Resource Locator (URL) to the resource ”for example, http://myserver/exchange/alias/inbox . The Async parameter is a Boolean that specifies whether the call is asynchronous. If set to True , which is the default, the call returns immediately. Finally, you can use the User and Password parameters to pass the username and password with which you want the component to access secured sites. The following JavaScript code example, taken from the coursexml.asp file in the Training application (included among the book's sample content), shows how to create an XMLHTTP object and use the Open method:
request = new ActiveXObject("Microsoft.XMLHTTP"); //Example propfind //request.open("PROPFIND", strURL, true); request.open("SEARCH", strURL, true);
The SetRequestHeader method allows you to specify the name and value for an HTTP header. The most common headers you will set are Depth header and Content-Type header. A Depth header, defined in Request for Comments (RFC) 2518, specifies how deep in a hierarchy the request applies. For example, setting the Depth header to " 1, noroot" means that the method will be applied to all the children of the specified URL but not to the URL itself. If you do not specify a depth, Exchange will default to an infinite depth. A Content-Type header, defined in RFC 1049, specifies the structure of the message body you plan to send to the server. The following code snippet shows how to use this method:
//For propfind you can select a depth //request.setRequestHeader("Depth", "1,noroot"); request.setRequestHeader("Content-Type", "text/xml");
The ReadyState property contains the state of the request object. Table 16-1 lists the five possible values.
Value | Description |
---|---|
UNINITIALIZED | The object has been created, but the Open method has not been called. |
LOADING | The object has been created, but the Send method has not been called. |
LOADED | The Send method has been called, but the response is not yet available. |
INTERACTIVE | The object is not yet fully loaded, but the user can already interact with it. Partial results can be viewed in the browser. |
COMPLETED | All data has been received and can be viewed in the browser. |
The OnReadyStateChange property allows you to specify which event handler to call when the ReadyState property changes. The following code sets the function to be called to dostatechange . You'll see what dostatechange does in a moment, when we look at the responseXML property.
request.onreadystatechange = dostatechange;
As you would guess, the Send method sends the request to the server. You specify the request as a string parameter to this method. The following code sends the body of our request. You'll see what this body looks like later in the chapter, when we examine WebDAV requests.
request.send(body);
The responseBody , responseStream , responseText , and responseXML properties allow you to retrieve the response in each type of format. You'll most often use responseText and responseXML in your applications. The responseStream property returns the response as an IStream object. The responseText property returns the XML response as a text string. The responseXML property returns the response as an XML document parsed by the MSXML parser, which means you'll receive an object that you can format using XSL or you can call methods on objects in the XMLDOM to interact with the data. You'll use these properties in the event handler you specified for the onreadystatechange property. The following JavaScript code (interlaced with server-side code for dDateStart and dDateEnd ) gets the XML response and formats it via XSL:
thexml = request.responseXML; datediv.innerHTML = "<B>Showing Courses from <%=dDateStart%> " + "to <%=dDateEnd%></B><BR>"; //Check for empty body if (thexml.selectSingleNode("a:multistatus/a:response") == null) { msgdiv.innerHTML = "<B>No courses found.</B>"; request = null; return; } //For debugging purposes //alert(request.responseText); msgdiv.innerHTML = thexml.transformNode(reportXSL.documentElement);
The Status and StatusText properties contain status information about the request. Status contains the HTTP status returned by the request. This is an integer that corresponds to an HTTP status code. StatusText returns a string that represents the status returned by the request. The following code checks to see whether the Status property has a value of 207, which indicates that the request was successful. If Status does not have a value of 207, the code will print out the values of the Status and StatusText properties as an error.
if(request.status != 207) { msgdiv.innerText = "Error, status = " + request.status + " " + request.statusText; msgdiv.style.fontFamily = "verdana" }
The Abort method cancels the current HTTP request and restores the XMLHTTP component to the UNINITIALIZED state. (See Table 16-1, shown earlier.)