Partager via


Searching Folders (WebDAV)

Topic Last Modified: 2006-06-12

This topic shows how to construct and send a WebDAV SEARCH Method request. The Structured Query Language (SQL) query is packaged as a value of an XML element that is sent to the server by using the XMLHTTP Component Object Model (COM) component.

See Constructing Exchange Store HTTP URLs and Authentication and Security Using WebDAV for more information.

This topic contains Microsoft® Visual Basic® Scripting Edition (VBScript), Microsoft C#, and Visual Basic .NET code examples.

The following example shows a SEARCH Method request:

SEARCH /public/folder1/ HTTP/1.1
Content-Type: text/xml
Content-Length: XXX
...

<?xml version="1.0"?>
<D:searchrequest xmlns:D = "DAV:" >
   <D:sql>
SELECT "DAV:displayname"  FROM "http://myserver/vroot/folder1/"
WHERE "DAV:ishidden" = false AND "DAV:isfolder" = false
   </D:sql>
</D:searchrequest>

See Exchange Store SQL for supported SQL grammar syntax, indexed properties, unsupported SQL, and other search reference topics.

Example

VBScript

The following example can be used to get search result values by manipulating the returned XML Document Object Model (DOM) Document object. The getItemsbyTagName method is used to create a collection of nodes containing values for one of the properties in your SQL SELECT Statement. See Property Names and WebDAV for more information.

Example

Option Explicit

' Variables.
Dim strURL      ' As String
Dim reqDoc      ' As Msxml2.DOMDocument
Dim resDoc      ' As Msxml2.DOMDocument
Dim pi          ' As IXMLDOMProcessingInstruction
Dim strPassword     ' As String
Dim strUserName     ' As String
Dim searchrequestNode   ' As IXMLDOMNode
Dim sqlNode             ' As IXMLDOMNode
Dim strQuery        ' As String
Dim queryNode       ' As IXMLDOMText
Dim req         ' As MSXML2.XMLHTTP
Dim objNodeList     ' As IXMLDOMNodeList
Dim objNode     ' As IXMLDOMNode
Dim i           ' As Integer

' Initialize variables.
strUserName = "Domain\user"
strPassword = "!Password"
strURL = "https://server/public/TestFolder1/"
set reqDoc = createobject("microsoft.xmldom")
set resDoc = createobject("microsoft.xmldom")
set pi = reqDoc.createProcessingInstruction("xml","version=""1.0""")

' Append processing instruction node to the DOM document.
reqDoc.appendChild pi

' Create the DAV:searchrequest node and set it
' to the root element of the document.
set searchrequestNode = reqDoc.createNode(1,"searchrequest","DAV:")
set reqDoc.documentElement = searchrequestNode

' Create the DAV:sql node and append it to the root element.
set sqlNode = reqDoc.createNode(1,"sql","DAV:")
searchrequestNode.appendChild sqlNode

' Build the SQL query.
strQuery = "SELECT ""DAV:displayname""  FROM """ & strURL
strQuery = strQuery & """ WHERE ""DAV:ishidden"" = false AND ""DAV:isfolder"" = false"

' Create the SQL query textnode and append it to document.
set queryNode = reqDoc.createTextNode(strQuery)
sqlNode.appendChild queryNode

' Create the XMLHTTP object.
set req = createobject("msxml2.xmlhttp")

' Specify the SEARCH method, the URL, that the request will be sent synchronously,
' the user name, and the password.
req.open "SEARCH", strURL, false, strUserName, strPassword

' Set the Content-Type header to "text/xml".
req.setrequestheader "Content-Type", "text/xml"

' Send the SEARCH request.
req.send reqDoc

' An error occurred on the server.
If req.status >= 500 Then

   ' Display request status and status text.
   wscript.echo "Status: " & req.status
   wscript.echo "Status text: An error occurred on the server."

' Success. Display the item display names.
ElseIf req.status = 207 Then

   ' Display request status and status text.
   wscript.echo "Status: " & req.status
   wscript.echo "Status text:  " & req.statustext

   ' Get the XML response.
   set resDoc = req.responseXML

   ' Build a list of the DAV:displayname XML nodes, corresponding to the folders
   ' returned in the search request. The DAV: namespace is typically
   ' assigned the a: prefix in the XML response body.
   Set objNodeList = resDoc.getElementsByTagName("a:displayname")

   If objNodeList.length > 0 Then
      wscript.echo "Non-folder item display names..."
      For i = 0 To (objNodeList.length -1)
         Set objNode = objNodeList.nextNode
         wscript.echo "   " & objNode.Text
   Else
      wscript.echo "No non-folder items found..."
   End If

Else
   ' Display the status, status text, and response text.
   wscript.echo "Status: " & req.status
   wscript.echo "Status text: " & req.statustext
   wscript.echo "Response text: " & req.responsetext

End If

' Clean up.
Set req = nothing

C#

The following example uses the System.Net.HttpWebRequest object to return the display names of non-folder items in a folder.

Example

using System;
using System.Net;
using System.IO;
using System.Text;
using System.Xml;

namespace ExchangeSDK.Snippets.CSharp
{
   class SearchingFoldersWebDAV
   {
      [STAThread]
      static void Main(string[] args)
      {
         // Variables.
         System.Net.HttpWebRequest Request;
         System.Net.WebResponse Response;
         System.Net.CredentialCache MyCredentialCache;
         string strRootURI = "https://server/public/TestFolder1/";
         string strUserName = "UserName";
         string strPassword = "!Password";
         string strDomain = "Domain";
         string strQuery ="";
         byte[] bytes = null;
         System.IO.Stream RequestStream = null;
         System.IO.Stream ResponseStream = null;
         XmlDocument ResponseXmlDoc = null;
         XmlNodeList DisplayNameNodes = null;

         try
         {
            // Build the SQL query.
            strQuery = "<?xml version=\"1.0\"?><D:searchrequest xmlns:D = \"DAV:\" >"
                        + "<D:sql>SELECT \"DAV:displayname\" FROM \"" + strRootURI + "\""
                        + "WHERE \"DAV:ishidden\" = false AND \"DAV:isfolder\" = false"
                        + "</D:sql></D:searchrequest>";

            // Create a new CredentialCache object and fill it with the network
            // credentials required to access the server.
            MyCredentialCache = new System.Net.CredentialCache();
            MyCredentialCache.Add( new System.Uri(strRootURI),
               "NTLM",
               new System.Net.NetworkCredential(strUserName, strPassword, strDomain)
               );

            // Create the HttpWebRequest object.
            Request = (System.Net.HttpWebRequest)HttpWebRequest.Create(strRootURI);

            // Add the network credentials to the request.
            Request.Credentials = MyCredentialCache;

            // Specify the method.
            Request.Method = "SEARCH";

            // Encode the body using UTF-8.
            bytes = Encoding.UTF8.GetBytes((string)strQuery);

            // Set the content header length.  This must be
            // done before writing data to the request stream.
            Request.ContentLength = bytes.Length;

            // Get a reference to the request stream.
            RequestStream = Request.GetRequestStream();

            // Write the SQL query to the request stream.
            RequestStream.Write(bytes, 0, bytes.Length);

            // Close the Stream object to release the connection
            // for further use.
            RequestStream.Close();

            // Set the content type header.
            Request.ContentType = "text/xml";

            // Send the SEARCH method request and get the
            // response from the server.
            Response = (HttpWebResponse)Request.GetResponse();

            // Get the XML response stream.
            ResponseStream = Response.GetResponseStream();

            // Create the XmlDocument object from the XML response stream.
            ResponseXmlDoc = new XmlDocument();
            ResponseXmlDoc.Load(ResponseStream);

            // Build a list of the DAV:href XML nodes, corresponding to the folders
            // in the mailbox.  The DAV: namespace is typically assgigned the a:
            // prefix in the XML response body.
            DisplayNameNodes = ResponseXmlDoc.GetElementsByTagName("a:displayname");

            if(DisplayNameNodes.Count > 0)
            {
               Console.WriteLine("Non-folder item display names...");

               // Loop through the display name nodes.
               for(int i=0; i<DisplayNameNodes.Count; i++)
               {
                  // Display the non-folder item displayname.
                  Console.WriteLine(DisplayNameNodes[i].InnerText);
               }
            }
            else
            {
               Console.WriteLine("No non-folder items found...");
            }

            // Clean up.
            ResponseStream.Close();
            Response.Close();

         }
         catch(Exception ex)
         {
            // Catch any exceptions. Any error codes from the SEARCH
            // method request on the server will be caught here, also.
            Console.WriteLine(ex.Message);
         }
      }
   }
}

Visual Basic .NET

The following example uses the System.Net.HttpWebRequest object to return the display names of non-folder items in a folder.

Example

Option Explicit On
Option Strict On

Module Module1

Sub Main()

   ' Variables
   Dim Request As System.Net.HttpWebRequest
   Dim Response As System.Net.HttpWebResponse
   Dim MyCredentialCache As System.Net.CredentialCache
   Dim strPassword As String
   Dim strDomain As String
   Dim strUserName As String
   Dim strRootURI As String
   Dim strQuery As String
   Dim bytes() As Byte
   Dim RequestStream As System.IO.Stream
   Dim ResponseStream As System.IO.Stream
   Dim ResponseXmlDoc As System.Xml.XmlDocument
   Dim DisplayNameNodes As System.Xml.XmlNodeList

   Try
      ' Initialize variables.
      strUserName = "UserName"
      strPassword = "!Password"
      strDomain = "Domain"
      strRootURI = "https://server/public/TestFolder1/"

      ' Build the SQL query.
      strQuery = "<?xml version=""1.0""?>" & _
         "<D:searchrequest xmlns:D = ""DAV:"" >" & _
         "<D:sql>SELECT ""DAV:displayname"" FROM """ & strRootURI & """" & _
         "WHERE ""DAV:ishidden"" = false AND ""DAV:isfolder"" = false" & _
         "</D:sql></D:searchrequest>"

      ' Create a new CredentialCache object and fill it with the network
      ' credentials required to access the server.
      MyCredentialCache = New System.Net.CredentialCache
      MyCredentialCache.Add(New System.Uri(strRootURI), _
         "NTLM", _
         New System.Net.NetworkCredential(strUserName, strPassword, strDomain) _
         )

      ' Create the PUT HttpWebRequest object.
      Request = CType(System.Net.WebRequest.Create(strRootURI), _
      System.Net.HttpWebRequest)

      ' Add the network credentials to the request.
      Request.Credentials = MyCredentialCache

      ' Specify the SEARCH method.
      Request.Method = "SEARCH"

      ' Encode the body using UTF-8.
      bytes = System.Text.Encoding.UTF8.GetBytes(strQuery)

      ' Set the content header length.  This must be
      ' done before writing data to the request stream.
      Request.ContentLength = bytes.Length

      ' Get a reference to the request stream.
      RequestStream = Request.GetRequestStream()

      ' Write the message body to the request stream.
      RequestStream.Write(bytes, 0, bytes.Length)

      ' Close the Stream object to release the connection
      ' for further use.
      RequestStream.Close()

      ' Set the Content Type header.
      Request.ContentType = "text/xml"

      ' Set the Translate header.
      Request.Headers.Add("Translate", "F")

      ' Send the SEARCH method request and get the
      ' response from the server.
      Response = CType(Request.GetResponse(), System.Net.HttpWebResponse)

      ' Get the XML response stream.
      ResponseStream = Response.GetResponseStream()

      ' Create the XmlDocument object from the XML response stream.
      ResponseXmlDoc = New System.Xml.XmlDocument
      ResponseXmlDoc.Load(ResponseStream)

      ' Build a list of the DAV:href XML nodes, corresponding to the folders
      ' in the mailbox.  The DAV: namespace is typically assgigned the a:
      ' prefix in the XML response body.
      DisplayNameNodes = ResponseXmlDoc.GetElementsByTagName("a:displayname")

      ' Loop through the returned items (if any).
      If DisplayNameNodes.Count > 0 Then

         Console.WriteLine("Non-folder item display names...")

         Dim i As Integer
         For i = 0 To DisplayNameNodes.Count - 1

            ' Display the non-folder item displayname.
            Console.WriteLine(DisplayNameNodes(i).InnerText)

      Else

         Console.WriteLine("No non-folder items found...")

      End If

      ' Clean up.
      ResponseStream.Close()
      Response.Close()

   Catch ex As Exception

      ' Catch any exceptions. Any error codes from the
      ' SEARCH method requests on the server will be caught
      ' here, also.
      Console.WriteLine(ex.Message)

   End Try

End Sub

End Module

See Also

Other Resources

WebDAV Protocol Status Codes