Introducing WebDav, getting appointments

Hello everybody, today I will introduce a very cool technology called WebDav, I think most of you know about this technology, but possibly this post will be helpful for newbies or those who is trying to choose from different technologies to access MS Exchange server.
(You can find a lot of very cool resources related to the WebDav using your favourite browser, for example here – http://en.wikipedia.org/wiki/WebDAV).

The biggest benefit of the WebDav is that this technology based on the HTTP protocol and doesn’t depend from Windows platform. So you can simply organize access to the corporate MS Exchange server from mobile phone, linux computer, tablet pc or from any other kind of devices which are support HTTP protocol. And it is cool!

Yep, syntax is not easy at the first sight, but it can be quickly learned because there are a lot of examples in the network.

Alternative approaches to access MS Exchange are very platform dependent, such as MAPI.

Using WebDav you can simply send a request to the Exchange server with XML message as a command to produce some action, what could be simplier? 🙂

For example, code to get all appointments from the Exchange server:

Original specification of WebDav protocol: http://www.webdav.org/specs/rfc2518.html

Code Snippet, original version: http://social.technet.microsoft.com/Forums/en-US
/exchangesvrdevelopment/thread/c566fdf0-3c8a-4499-96b2-a9d7554d15f9/

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

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

public partial class WebDavTestRead : System.Web.UI.Page
{
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;

protected void Page_Load(object sender, EventArgs e)
{
// Exchange server name;
strExchSvrName = “yourserver.yourdomain.com”;

// Mailbox folder name.
strMailbox = “calendarName”;

// URI of the user’s calendar folder.
strCalendarUri = “https://” + strExchSvrName + “/exchange/”
+ strMailbox + “/Calendar/”;

// User name and password of appointment creator.
strUserName = “username”; // must have permission to read from the calendarName
strDomain = “domain”;
strPassword = “password”;

string query = “
+ “SELECT “http://schemas.microsoft.com/exchange/outlookmessageclass”, “DAV:contentclass”, “DAV:displayname” FROM “” + strCalendarUri + “””
+ “WHERE “DAV:ishidden” = true AND “DAV:isfolder” = false”
+ “
“;

query = “
+ “
+ “
+ “SELECT “
+ “”DAV:displayname”, ” // Just the appt Uri portion of the resource
+ “”DAV:href”, ” // The full resource Uri of the appt
+ “”urn:schemas:httpmail:subject”, ” // Subject of appt
+ “”urn:schemas:calendar:dtstart”, ” // Start date/time of appt
+ “”urn:schemas:calendar:dtend”, ” // End date/time of appt
+ “”urn:schemas:httpmail:textdescription”, ” // Body of appt
+ “”urn:schemas:calendar:location”, ” // Location of appt
+ “”urn:schemas:calendar:alldayevent”, ” // Whether appt is an all day appt
+ “”urn:schemas:calendar:meetingstatus”, ” // The confimed status of the appt
+ “”urn:schemas:calendar:busystatus”, ” // The comitted status the appt represents
+ “”http://schemas.microsoft.com/mapi/proptag/x823D0003″, ” // The color of the appt
+ “”urn:schemas:calendar:reminderoffset”, ” // The reminder offset of the appt
+ “”DAV:ishidden”, ” // Whether this is hidden
+ “”urn:schemas:calendar:instancetype”, ” // The relation of the appt to a recurring series
+ “”urn:schemas:calendar:transparent”, ” // The transparency of the appt to free/busy searches
+ “”urn:schemas:calendar:timezoneid” ” // The display timezone of the appt
+ “FROM Scope(‘SHALLOW TRAVERSAL OF “” + strCalendarUri + “”‘) “
+ “WHERE “
+ “(“DAV:contentclass” = ‘urn:content-classes:appointment’ ) ” // Item is an appt
+ “AND (NOT “urn:schemas:calendar:instancetype” = 1) ” // Appt is not the master of a recurring series (i.e. pull single appts or instances of recurring appts)
+ “AND (“urn:schemas:calendar:dtend” > ‘” + Convert.ToDateTime(“3-12-2007”).Date.ToUniversalTime().ToString(“yyyy/MM/dd HH:mm:ss”) + “‘) ” // Appt ends after the start of our range
+ “AND (“urn:schemas:calendar:dtstart” < ‘” + Convert.ToDateTime(“3-17-2007”).Date.ToUniversalTime().ToString(“yyyy/MM/dd HH:mm:ss”) + “‘) ” // Appt begins before the end of our range
+ “AND (“DAV:displayname” like ‘” + “LS.ImportantDates.” + “%’ ) “
+ “ORDER BY “urn:schemas:calendar:dtstart” “
+ “

+ “
“;

// 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(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. This must be
// done before writing data to the request stream.
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);

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

// Set the content type header.
WebDavRequest.ContentType = “text/xml”;

try
{
WebDavResponse = (System.Net.HttpWebResponse)WebDavRequest.GetResponse();
Response.Write(“Calendar read succeeded.”);
Response.Write(“Status Code: ” + WebDavResponse.StatusCode);
Response.Write(“Status Description: ” + WebDavResponse.StatusDescription);

using (System.IO.StreamReader streamReader = new System.IO.StreamReader(WebDavResponse.GetResponseStream()))
{
Response.Write(streamReader.ReadToEnd());
}

// Clean up.
WebDavResponse.Close();
}
catch (System.Net.WebException webException)
{
Response.Write(“Calendar read failed.”);
Response.Write(webException.Message);

WebExceptionStatus status = webException.Status;
if (status == WebExceptionStatus.ProtocolError)
{
// Record the error
Response.Write(“The server returned protocol error”);

// Get the HttpWebResponse so we can check the HTTP status code
Response.Write(“Status Code: ” + ((HttpWebResponse)webException.Response).StatusCode);
Response.Write(“Status Description: ” + ((HttpWebResponse)webException.Response).StatusDescription);

using (System.IO.StreamReader streamReader = new System.IO.StreamReader(((HttpWebResponse)webException.Response).GetResponseStream()))
{
Response.Write(streamReader.ReadToEnd());
}
}
}

}

}

Basing on this example you can simply retrieve all appointments (calendar items) from your server.

Note: in WebDav used not only GET and POST request methods, pay attention that different operations use different request methods, for example, to delete an appointment you have to specify ‘DELETE’ request method and simply make a request to the appointment’s URI.

Happy coding (:

Best regards,
Yahor