Tag Archives: WebDAV

While try to log into an Exchange 2003 mailbox by using WebDAV program, you receive a 401 status code in IE


When the user tried to access a Microsoft Exchange Server 2003 mailbox by using a program that uses Web Distributed Authoring and Versioning (WebDAV), Internet Explorer throws 401 HTTP status code. During investigation we found that we may not be able to access the mailbox.

Also we notice that the mailbox has never received an e-mail message, and a user has never logged on to the mailbox. After checking the application log, we notice the following event logged in it:

Event Type: Error
Event Source: MSExchangeIS Mailbox Store
Event Category: Logons
Event ID: 1022
Description:
Logon Failure on database "Storage Group NameMailbox Store (xxxxxxx)"

At end of analysis, we noticed that the mailbox is the recently created one.

By design, when a mailbox object is created in the Exchange information store, the mailbox object is not available by WebDAV until the mailbox is accessed through a client logon. If the mailbox receives an e-mail message, the mailbox object becomes available, but not in a way that permits the WebDAV program access. So, the problem still occurs.

To overcome this, log on to the mailbox by using one of the following clients before you run the WebDAV program:

  • Log on to the mailbox by using a Outlook.
  • Log on to the mailbox by using the Outlook Web Access (OWA).
  • Log on to the mailbox by using a custom application

Happy troubleshooting!

Troubleshooting: IIS/Exchange logs and WebDAV functions


You can collect information about client requests by enabling logging for sites and services. IIS logs are stored in %SystemRoot%system32Logfiles<service_name>. If you examine the IIS/Exchange log file you will see the request for the sample application being handled by IIS – you can notice couple of jargons like GET, PUT, POST, MKCOL, LOCK, UNLOCK, PROPFIND, SEARCH, PROPATCH, SUSBCRIBE, UNSUBSCRIBE, POLL etc.

clip_image002

The three main HTTP functions used are GET, PUT and POST:

  • GET: Retrieves a document 

  • PUT: Puts an item in a folder 

  • POST: Submits an item to a folder

In addition to above, there are few more WebDAV functions that are used:

  • MKCOL: Makes a collection that is in essence the same as a Web Storage System folder. MKCOL allows you to make folders and set their properties. 

  • LOCK: Locks documents to prevent writes. 

  • UNLOCK: Allows writes and creates updates. 

  • PROPFIND: Searches for properties individually or for a whole set of folders. 

  • SEARCH: Provides filter, subquery and sort capabilities to a search. 

  • PROPPATCH: Sets arbitrary properties on an item. 

  • SUBSCRIBE: Adds a user to a list. 

  • UNSUBSCRIBE: Removes a user from a list. 

  • POLL: Checks to see if the notification is fired.

Happy troubleshooting!!

Part 1 : Developer Roadmap – Development Technologies for Exchange Server 2010


This two part article is targeted for the developer audience, if you’re the developer who want to create a develop custom application for Exchange Server 2010 or already has custom application designed for previous versions of Exchange Server 2010.

Some Exchange programming technologies that are available in versions of Exchange earlier than Microsoft Exchange Server 2010 are obsolete and have been replaced with other technologies. Per MSDN article, the programming technologies and APIs stated below have either been removed from Exchange 2010 or earlier versions of Exchange, are no longer supported for use with the current version of Exchange, or are no longer the recommended API to use to access Exchange.

Recommendation: We recommend that you use Exchange PowerShell commands to administer Exchange configuration data.

Recommendation: We recommend that you migrate your applications that use CDOEX to Exchange Web Services.

Recommendation: We recommend that you migrate your applications that use CDOEXM to use Exchange PowerShell commands.

Recommendation: We recommend that you migrate your applications that use CDOWF to use Windows Workflow Foundation Services.

Recommendation: Notification-based applications that work with Exchange 2010 should use transport agents.

Recommendation: We recommend that you migrate any CDO 1.2.1 applications to use Exchange Web Services.

Recommendation: To ensure continued future compatibility, we recommend that you consider migrating your ICS applications to use Exchange Web Services notifications.

Recommendation: We recommend that you migrate applications that use ExOLEDB to use Exchange Web Services.

  • Exchange Rules DLL is part of the sample code that shipped with the Exchange 5.5 and Exchange 2000 SDKs.

Recommendation: We recommend that you migrate applications that use the Exchange Rules DLL to use either MAPI or Exchange Web Services notifications.

Recommendation: Where possible, we recommend that applications that use Exchange Store Event sinks be migrated to use either transport agents or Exchange Web Services notifications.

Recommendation: We recommend that you migrate backup and restore applications that use streaming backup to use the Windows Volume Shadow Copy Service (VSS).

Recommendation: We recommend that you migrate applications that use Exchange WebDAV to use the Exchange Web Services.

Recommendation: We recommend that you migrate applications that use Exchange WebDAV notifications to use Exchange Web Services notifications.

Recommendation: We recommend that you migrate applications that use Exchange Web Forms to use either Windows SharePoint Services, or Active Server Pages.

Recommendation: We recommend that you use Exchange PowerShell commands to administer Exchange configuration data.

Recommendation: We recommend that you migrate applications that used WMI to use the Exchange PowerShell commands.

Happy Programming!!

Exchange Server Utility : PFDAVAdmin update is released


I use PFDAVAdmin  utility [Exchange Server Public Folder Distributed Authoring and Versioning (DAV)-based Administration tool]  to perform various management tasks related to public folders and mailboxes. An updated version of the PFDAVAdmin tool has been released to the web on 04/06/2010 (the prior version on the Download Center was from April of 2007) @ Microsoft Download Center. You can get it from the download center at this link: http://www.microsoft.com/downloads/details.aspx?familyid=635BE792-D8AD-49E3-ADA4-E2422C0AB424.

Per MSExchange.com’s blog post, this update contains various bug fixes that have been made over the last three years. It also has some changes that make it work better against Exchange 2007. If you need similar functionality for Exchange 2010, use ExFolders instead

Please note:

  • The dependency on .NET Framework 1.1 remains, which means you should run PFDAVAdmin from a workstation with Framework 1.1 installed – you should not install this old version of the framework on your Exchange servers, because it makes IIS unhappy.
  • PFDAVAdmin still cannot connect to Exchange 2010 servers, because WebDAV is gone from 2010.

Update : Technologies not available with Exchange 2010 & their migration reference(s)


Some development technologies that shipped/available in earlier versions of Exchange Server are not included in Exchange 2010.

The following technologies were removed from Exchange 2007:

  • Exchange providers for Windows Management Instrumentation (WMI)
  • Collaboration Data Objects for Exchange Management (CDOEXM)
  • Collaboration Data Objects for Exchange Workflow (CDOWF)
  • Exchange Web Forms
  • At Functions
  • DAPI.DLL

The following technologies were removed from Exchange 2010:

  • Exchange OLE DB Provider (ExOLEDB)
  • Exchange store Event Sinks
  • World Wide Web Distributed Authoring and Versioning (WebDAV)
  • CDO 3.0 (CDOEx)
  • Item-level permissions
  • Exchange Store custom item types

These technologies are not documented in the Exchange 2010 Web Services SDK. Any references to these technologies in the documentation are in error.

For migration information, you can refer the Guide to Exchange Server 2010 Development Technologies.

WebDAV : How to retrieve list of folders from Exchange Server using Search method (WebDAV) programmatically ?


using System;
using System.Net;
using System.IO;
using System.Text;
using System.Xml;
 
namespace SampleCode
{
   class GetFolders
   {
     
     static void Main(string[] args)
      {
         // Variables.
         System.Net.HttpWebRequest Request;
         System.Net.WebResponse Response;
         System.Net.CredentialCache MyCredentialCache;
         string strRootURI = "http://server/exchange/username/Inbox/"; // Provide the valid URI
         string strUserName = "UserName";
         string strPassword = "Password";
         string strDomain = "Domain";
         string strQuery ="";
         byte[] bytes = null;
         System.IO.Stream RequestStream = null;
         System.IO.Stream ResponseStream = null;
         System.Xml.XmlTextReader XmlReader = null;
 
         try
         {
            // Build the SQL query.
            strQuery = "<?xml version="1.0"?><D:searchrequest xmlns:D = "DAV:" >";
            strQuery += "<D:sql>SELECT "DAV:href" FROM scope('hierarchical traversal of "";
            strQuery += strRootURI + ""')</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 XmlTextReader object from the XML
            // response stream.
            XmlReader = new XmlTextReader(ResponseStream);
 
            // Read through the XML response, node by node.
            while(XmlReader.Read())
            {
               // Look for the opening DAV:href node.  The DAV: namespace is
               //typically assigned the a: prefix in the XML response body.
               if(XmlReader.Name == "a:href")
               {
                  // Advance the reader to the text node.
                  XmlReader.Read();
 
                  // Display the value of the DAV:href text node.
                  Console.WriteLine("Value: " + XmlReader.Value);
                  Console.WriteLine("");
 
                  //Advance the reader to the closing DAV:href node.
                  XmlReader.Read();
               }
            }
 
            // Clean up.
            XmlReader.Close();
            ResponseStream.Close();
            Response.Close();
 
         }
         catch(Exception ex)
         {
            // Catch any exceptions. Any error codes from the SEARCH method request
            Console.WriteLine(ex.Message);
         }
      }
   }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Hope this helps.

Gotcha – PermanentURL & WebDAV Series # 2 – How to access flat URLs using CDO/MAPI


With continuation to previous blog post, this article describes how to access items in a WebDAV application that are identified by using MAPI. The WebDAV application uses flat URLs to access items or folders.

How to use flat URLs to access items by using MAPI ?

  1. Read property tag 0x670E001E by using MAPI on the folder or item to access.

  2. Save the returned value in a variable. The value will resemble the following:

    /-FlatUrlSpace-/ca09cf9efaad754e8a85909b04bb255c-12ee443

  3. Construct a URL that is used to access the folder or item that is using the flat URL. The URL will resemble the following:

    http://server/exchange/mailbox/-FlatUrlSpace-/ca09cf9efaad754e8a85909b04bb255c-12ee443

  4. Use the URL in a WebDAV call to access an item.

Best use of Flat URL usage in the Programming

Flat URLs do not have encoding and escaping rules and will work for folders and items in most DAV operations, with the following exceptions:

  • As destinations of MOVE or COPY operation
  • As a source for a DELETE
  • For Outlook Web Access URL commands; for example, ?cmd=[myCommand].

Use this property when you are stepping out of CDO 1.2.1 or MAPI code into WebDAV. The HREF in WebDAV is usually created from the subject that was typed in Microsoft Outlook. The subject in Outlook can contain characters that are encoded for use with DAV. This encoding resembles URL encoding. Instead of reverse engineering the encoding, use the flat URL to get the item.

Hope this helps.

Gotcha : Appointment created with WebDAV is not getting displayed in Outlook?


Issue:

One of my customer updated me that he created an appointment by using WebDAV. But the user has the following issues when he tries to view the mailbox owner’s calendar:

  • The appointment does not appear when Microsoft Outlook is in the Day, Week, or Month view.
  • The appointment appears correctly when the appointments are sorted by category.
  • The appointment appears correctly when the delegate user views the appointment by using Microsoft Outlook Web Access (OWA).

Why it’s happening?
Later when we started probing we found that the specific appointment doesn’t have dispidrecurring property or it is missing. This issue occurs if you do not explicitly set the dispidRecurring MAPI property in your program. When a schema name in your program is not specified, Outlook makes assumptions about the schema properties. Therefore, appointments that you create programmatically may not appear consistently when they are viewed in Outlook

Resolution:
To resolve this issue, specify the dispidRecurring property in your program as specified in the article, like, we need to include the data type namespaces, "xmlns:dt=""urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/""" in our WebDAV code.

But make sure, that we don’t fell prey to complex calendaring by setting dispidRecurring property as TRUE along with WebDAV, like by doing, "<mapi:0x00008223 dt:dt=""boolean"">1</mapi:0x00008223>". This excerpt sets the MAPI property to 1 (TRUE) to create a recurring appointment. To create a non-recurring appointment, set this property to 0 (FALSE). As the complex calendaring is not supported with WebDAV, you can refer the following article or the support KB, why complex calendaring is not supported and what is supported with WebDAV.

Exchange Server: How to retrieve appointments using C# & WebDAV?


Code Snippet (C#):

   //Declaration part
    string strExchSvrName = “”;
    string strMailbox = “”;
    string strCalendarUri = “”;
    string strDomain = “”;
    string strUserName = “”;
    string strPassword = “”;
    System.Net.HttpWebRequest WebDavRequest = null;
    System.Net.HttpWebResponse WebDavResponse = null;
    System.Net.CredentialCache MyCredentialCache = null;
    byte[] bytes = null;
    System.IO.Stream WebDavRequestStream = null;
 
     // Provide the Exchange server name;
      strExchSvrName = “mydomain.in”;
 
      // Provide Mailbox folder name.
       strMailbox = “Mailbox1”;
 
      //if HTTPS -then provide URI of the user’s calendar folder
      strCalendarUri = “https://” + strExchSvrName + “/exchange/”+ strMailbox + “/Calendar/”;
 
        //if HTTP -then provide URI of the user’s calendar folder
        //strCalendarUri = “http://” + strExchSvrName + “/exchange/” + strMailbox + “/Calendar/”;
 
        //Provide the User name and password of appointment creator. Make sure the user has enough permissions to read
        strUserName = “username”; 
        strDomain = “domain”;
        strPassword = “password”;
 
        //Build the Query
        string query = “<?xml version=”1.0”?><D:searchrequest xmlns:D = “DAV:” >”
                + “<D:sql>SELECT “http://schemas.microsoft.com/exchange/outlookmessageclass”, “DAV:contentclass”, 
“DAV:displayname” FROM “”
+ strCalendarUri + “””
                + “WHERE “DAV:ishidden” = true AND “DAV:isfolder” = false”
                + “</D:sql></D:searchrequest>”;
 
        query = “<?xml version=”1.0″?>”
                + “<dav:searchrequest xmlns:dav=”DAV:”>”
                + “<dav:sql>”
                + “SELECT “
                + “”DAV:displayname”, “ // Appointment Uri portion of the resource
                + “”DAV:href”, “ // Full resource Uri of the appointment
                + “”urn:schemas:httpmail:subject”, “ // Subject of appointment
                + “”urn:schemas:calendar:dtstart”, “ // Start date/time of appointment
                + “”urn:schemas:calendar:dtend”, “ // End date/time of appointment
                + “”urn:schemas:httpmail:textdescription”, “ // Body of appointment
                + “”urn:schemas:calendar:location”, “ // Location of appointment
                + “”urn:schemas:calendar:alldayevent”, “ // Whether appointments an all day appointment
                + “”urn:schemas:calendar:meetingstatus”, “ // Confimed status of the appointment
                + “”urn:schemas:calendar:busystatus”, “ // Comitted status the appointment represents
                + “”http://schemas.microsoft.com/mapi/proptag/x823D0003”, “ // Color of the appointment
                + “”urn:schemas:calendar:reminderoffset”, “ // Reminder offset of the appointment
                + “”DAV:ishidden”, “ // Whether this is hidden
                + “”urn:schemas:calendar:instancetype”, “ // Relation of the appointment to a recurring series
                + “”urn:schemas:calendar:transparent”, “ // Transparency of the appointment to free/busy searches
                + “”urn:schemas:calendar:timezoneid” “ // Display timezone of the appointment
                + “FROM Scope(‘SHALLOW TRAVERSAL OF “” + strCalendarUri + “”‘) “
                + “WHERE “
                + “(“DAV:contentclass” = ‘urn:content-classes:appointment’ ) “ // Item is an appointment
                + “AND (NOT “urn:schemas:calendar:instancetype” = 1) “ // appointment is not the master of a recurring series (Get single
appointments or instances of recurring appointments)
                + “AND (“urn:schemas:calendar:dtend” &gt; ‘” + 
                Convert.ToDateTime(“3-12-2007”).Date.ToUniversalTime().ToString(“yyyy/MM/dd HH:mm:ss”) + “‘)
//Appointment ends after the start of our range
                + “AND (“urn:schemas:calendar:dtstart” &lt; ‘” + 
Convert.ToDateTime(“3-17-2007”).Date.ToUniversalTime().ToString(“yyyy/MM/dd HH:mm:ss”) + “‘)
//Appointment begins before the end of our range
                + “AND (“DAV:displayname” like ‘” + “LS.ImportantDates.” + “%’ ) “
                + “ORDER BY “urn:schemas:calendar:dtstart” “
                + “</dav:sql>”
                + “</dav:searchrequest>”;
 
 
        //Provide credentials required to access the server. Here i used the NTLM
        MyCredentialCache = new System.Net.CredentialCache();
        MyCredentialCache.Add(new System.Uri(strCalendarUri), “NTLM”, new System.Net.NetworkCredential(strUserName, strPassword, strDomain));
 
        //Create the HttpWebRequest object.
        WebDavRequest = (System.Net.HttpWebRequest)HttpWebRequest.Create(strCalendarUri);
 
        // Add the network credentials to the request.
        WebDavRequest.Credentials = MyCredentialCache;
 
        // Specify the PROPPATCH method.
        WebDavRequest.Method = “SEARCH”;
 
        // Encode the body using UTF-8.
        bytes = Encoding.UTF8.GetBytes(query);
 
        // Set the content header length.
        WebDavRequest.ContentLength = bytes.Length;
 
        // Get a reference to the request stream.
        WebDavRequestStream = WebDavRequest.GetRequestStream();
 
        // Write the message body to the request stream.
        WebDavRequestStream.Write(bytes, 0, bytes.Length);
 
        // Release the connection
        WebDavRequestStream.Close();
 
        // Set the content type header.
        WebDavRequest.ContentType = “text/xml”;
 
       WebDavResponse = (System.Net.HttpWebResponse)WebDavRequest.GetResponse();
       Response.Write(“Calendar : “);
  Response.Write(“Status Code: “ + WebDavResponse.StatusCode + “Description: “ + WebDavResponse.StatusDescription);
       using (System.IO.StreamReader streamReader = new System.IO.StreamReader(WebDavResponse.GetResponseStream()))
       {
             Response.Write(streamReader.ReadToEnd());
       }
       WebDavResponse.Close();
        
 
     You can get more related samples and detailed information from Dan’s blog. For more information you can also refer this article .csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

How to authenticate the Inbox in Microsoft Exchange Server 2003 with forms-based authentication enabled?


Please find the Code Snippet Access Exchange Server 2003 using WebDAV in your Web application per KB:



   1:  ‘Declaration Section
   2:  Dim strServerName as String = “Server Name”     ‘TODO: Change to your environment
   3:  Dim strDomain as String = “Domain Name”       ‘TODO: Change to your environment
   4:  Dim strUserID as String = “Username”            ‘TODO: Change to your environment
   5:  Dim strPassword as String = “Password”        ‘TODO: Change to your environment
   6:   
   7:  ‘ Create our destination URL.
   8:  Dim strURL As String = “https:/” & strServerName & “/exchange” & strUserName & “/inbox/test.eml”
   9:  Dim strReusableCookies As String
  10:   
  11:  ‘ Create our Web request object.
  12:  GETRequest = CType(WebRequest.Create(New System.Uri(strURL & strApptItem)), HttpWebRequest)
  13:  strReusableCookies = AuthenticateSecureOWA(strServerName, strDomain, strUserID, strPassword)
  14:   
  15:  ‘ Add the cookie set that is obtained after OWA authentication to our request header.
  16:  PROPPATCHRequest.Headers.Add(“Cookie”, strReusableCookies)
  17:  PROPPATCHRequest.ContentType = “text/xml”
  18:  PROPPATCHRequest.KeepAlive = True
  19:  PROPPATCHRequest.AllowAutoRedirect = False
  20:   
  21:  ‘ Specify the PROPPATCH method.
  22:  PROPPATCHRequest.Method = “GET”
  23:   
  24:  ‘ Enter your WebDAV-related code here.
  25:  

.csharpcode {
BACKGROUND-COLOR: #ffffff; FONT-FAMILY: consolas, “Courier New”, courier, monospace; COLOR: black; FONT-SIZE: small
}
.csharpcode PRE {
BACKGROUND-COLOR: #ffffff; FONT-FAMILY: consolas, “Courier New”, courier, monospace; COLOR: black; FONT-SIZE: small
}
.csharpcode PRE {
MARGIN: 0em
}
.csharpcode .rem {
COLOR: #008000
}
.csharpcode .kwrd {
COLOR: #0000ff
}
.csharpcode .str {
COLOR: #006080
}
.csharpcode .op {
COLOR: #0000c0
}
.csharpcode .preproc {
COLOR: #cc6633
}
.csharpcode .asp {
BACKGROUND-COLOR: #ffff00
}
.csharpcode .html {
COLOR: #800000
}
.csharpcode .attr {
COLOR: #ff0000
}
.csharpcode .alt {
BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; WIDTH: 100%
}
.csharpcode .lnum {
COLOR: #606060
}

There are two ways of implementing this.


Method # 1: In the Visual Basic .NET code sample that was just mentioned, the strReusableCookies string variable is the authentication cookie that is returned from the AuthenticateSecureOWA function call. If the authentication cookie times out, call the AuthenticateSecureOWA function again to receive a new authentication cookie.

Method # 2: Put the WebDAV request in a try/catch block. The try/catch block will catch the authentication cookie time-out error. When the authentication cookie time-out error occurs, you can re-authenticate the Inbox in Exchange Server 2003 to the Exchange Server 2003 server that is enabled with forms-based authentication.

Gotcha – PermanentURL & WebDAV Series # 1


Take this scenario. One of my customer wanted to updated the contact fields using PR_ENTRY_ID and other fields. He can able to obtain the other all fields and getting issue with this property whenever he retrieve using WebDAV·  He gets garbage values at one client and another client it leads him to Exception.

In this scenario, instead of using the MAPI property, we can make use of PermanentURL. In order to access the property we need to make use of the following property:

 
Note: This property is unique across all servers.

There are certain things that needs to be considered when we use the PermanentURL is listed below:

If you use the permanenturl field, be aware of the following issues:

. This field is the field for a permanent URL that can always be used to access an item even if the URL to the item is either renamed or moved.

. The size of the permanenturl fields is computed according to the following conditions:

. The flat URL name uses the following format, where the folder ID (FID) and the message ID (MID) are in long format (GUID + ID). These IDs are unique on a server.

. For folders: http://server/virtual_root/-FlatUrlSpace-/text-format-fid-of-folder

. For messages: http://server/virtual_root/-FlatUrlSpace-/text-format-fid-of-folder/text-format-mid-of-message

. There must be hyphen (-) between the GUID and the ID.

. When you change the ID to a text format, you must leave out the leading zeros. The following text is an example of a flat URL to a folder whose FID is 1-287. This example assumes that replid 1 maps to GUID 3B6D774A33B6D211AEB500C04FB6B4C6:

   1:  "/-FlatUrlSpace-/3B6D774A33B6D211AEB500C04FB6B4C6-287"   

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The following text is an example of a flat URL to a message in folder 1-287 whose MID is 1-30A:

   1:  "/-FlatUrlSpace-/3B6D774A33B6D211AEB500C04FB6B4C6-287/3B6D774A33B6D211AEB500C04FB6B4C6-30A" 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The maximum size is:

   1:  http://long_server_name/long_virtual_root name/3B6D774A33B6D211AEB500C04FB6B4C6-FFFFFFFFFFFE/3B6D774A33B6D211AEB500C04FB6B4C6-FFFFFFFFFFFF  

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

. You cannot have two permanenturl values that differ by case that point to separate items. Computer names, virtual roots, GUIDs, and hexadecimal-format FIDs and MIDs are all defined as case-insensitive.

. To have successful queries, you may have to remove the section before "/-FlatUrlSpace-/b8d01…" in the syntax from the queries. For example, you may have to remove http://servername/folder from the following query:

"http://servername/folder/-FlatUrlSpace-/b8d01…&#160;

The following section includes examples of queries.

. To test with webDAV (HTTP), run either of the following queries:

   1:  <sql> Select "http://schemas.microsoft.com/exchange/permanenturl","DAV:id 
   2:   
   3:  http://schemas.microsoft.com/exchange/permanenturl" FROM Scope('SHALLOW 
   4:   
   5:  TRAVERSAL OF ""') WHERE "http://schemas.microsoft.com/exchange/permanenturl" = 
   6:   
   7:  /-FlatUrlSpace-/b8d014e9f474644ba656cb6adcef9d7b-1c/b8d014e9f474644ba656cb6adcef9d7b-1de6'

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

-or-

   1:  <sql> Select "http://schemas.microsoft.com/exchange/permanenturl","DAV:id 
   2:   
   3:  http://schemas.microsoft.com/exchange/permanenturl" FROM Scope('SHALLOW 
   4:   
   5:  TRAVERSAL OF ""') WHERE "http://schemas.microsoft.com/exchange/permanenturl" = 
   6:   
   7:  'http://servername/folder/-FlatUrlSpace-/b8d014e9f474644ba656cb6adcef9d7b-1c/b8d014e9f474644ba656cb6adcef9d7b-1de6'  

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

. To test with Microsoft ActiveX Data Objects (ADO) (the ExOLEDB file), run either of the following queries:

   1:  SELECT "http://schemas.microsoft.com/exchange/permanenturl" FROM scope('shallow traversal of 
   2:   
   3:  "file://./backofficestorage/mycompany.com/MBX/user/Calendar"' 
   4:   
   5:  file://./backofficestorage/mycompany.com/MBX/user/Calendar) 
   6:   
   7:  WHERE "http://schemas.microsoft.com/exchange/permanenturl" = 
   8:   
   9:  '/-FlatUrlSpace-/b8d014e9f474644ba656cb6adcef9d7b-1c/b8d014e9f474644ba656cb6adcef9d7b-1db5' 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

-or-

   1:  SELECT "http://schemas.microsoft.com/exchange/permanenturl" FROM scope('shallow traversal of 
   2:   
   3:  "file://./backofficestorage/mycompany.com/MBX/user/Calendar"' 
   4:   
   5:  file://./backofficestorage/mycompany.com/MBX/user/Calendar)WHERE "http://schemas.microsoft.com/exchange/permanenturl" = 
   6:   
   7:  'file://./backofficestorage/servername/folder/-FlatUrlSpace-/b8d014e9f474644ba656cb6adcef9d7b-1c/b8d014e9f474644ba656cb6adcef9d7b-1db5'  

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }