Using .NET and WebDAV to access an Exchange server

by Marc Charbonneau on 26/10/2006

If your company runs on Exchange (and who doesn’t), there will come a day when you’ll need to gather or modify data from an external application or a web page you’re building. There are many tools for doing this, from expensive third-party libraries to dead technologies buried in MSDN. The method I found best was a mix of C#, .NET and WebDAV, all of which are modern, flexible, and recommended by Microsoft. WebDAV (basically an HTTP request that can write as well as read) is used in many applications, including Microsoft’s own Entourage. It’s reliable and easy to use, but there are plenty of potential problems if you’re starting from scratch. Here’s a short tutorial that should give you all the basics for building Exchange support into your own application.

Getting Started

Because WebDAV is built on standard HTTP requests, the .NET library classes can handle many of the gritty details. We need to start by authenticating with a set of login credentials to get an authorization cookie, request the data we need, and extract it into a format we understand. To keep things simple, I’m only going to create one class, WebDAVRequest. I’m going to stick a few variables in here, to define things like the username and server address. Remember to URL encode the path if it contains any non-alphanumeric characters.


using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Security.Authentication;
using System.Text.RegularExpressions;

namespace DowntownSoftwareHouse.ExchangeExample
{
    public class WebDAVRequest
    {
        private static string server = "https://mail.mycompany.com";
        private static string path = "/public/Calendars/Board%20Room";
        private static string username = "user"
        private static string password = "password";
        private CookieContainer authCookies = null;
    }
}

Authentication

We’re going to be using forms based authentication in this example. The code you need to write does pretty much the same thing as when you log into your OWA server using a web browser; the local client checks the server’s certificate, attempts to authenticate using your credentials, and stores a cookie for later requests. Put these methods into the class we just wrote.


/// 
/// Add code here to check the server certificate, if you think it's necessary. Note that this
/// will only be called once when the application is first started.
/// 

protected bool CheckCert( Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors )
{
    return true;
}

/// 
/// Default WebDAVRequest constructor. Set the certificate callback here.
/// 

public WebDAVRequest()
{
    ServicePointManager.ServerCertificateValidationCallback += CheckCert;
}

The CheckCert event handler is called once when you first connect to the Exchange server. You’ll see that I’m cheating here; this code doesn’t actually do anything except allow us to move on to the next step. Whether or not you verify the certificate’s authenticity depends on the security of your network, and I’ll leave that decision up to you. For now, let’s move on.


/// 
/// Authenticate against the Exchange server and store the authorization cookie so we can use
/// it for future WebDAV requests.
/// 

public void Authenticate()
{
    string authURI = server + "/exchweb/bin/auth/owaauth.dll";

    // Create the web request body:

    string body = string.Format( "destination={0}&username={1}&password={2}", server + path, username, password );
    byte[] bytes = Encoding.UTF8.GetBytes( body );

    // Create the web request:

    HttpWebRequest request = (HttpWebRequest)System.Net.WebRequest.Create( authURI );
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    request.CookieContainer = new CookieContainer();
    request.ContentLength = bytes.Length;

    // Create the web request content stream:

    using ( Stream stream = request.GetRequestStream() )
    {
        stream.Write( bytes, 0, bytes.Length );
        stream.Close();
    }

    // Get the response & store the authentication cookies:

    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    if ( response.Cookies.Count < 2 )
        throw new AuthenticationException( "Login failed. Is the login / password correct?" );

    cookies = new CookieContainer();
    foreach ( Cookie myCookie in response.Cookies )
    {
        cookies.Add( myCookie );
    }

    response.Close();
}

Things are getting a bit trickier now. This might be a little unfamiliar if you haven't worked with HTTP data streams in the past, but .NET encapsulates most of it. All we're doing is sending an HTTP request (which contains our login credentials, as well as the URL to the resource we're requesting access to) to the Exchange OWA server's authorization .dll, and reading back the response. If everything goes okay, we'll get a few cookies which will be used later to access the resource we need. Note that we have to move these from a CookieCollection to a CookieContainer; for reasons I don't know .NET doesn't let you intermix the containers for requests and responses.

Don't forget to close the response stream; you'll get errors the next time you make a request if you don't.

Gathering Data

At this point, we're finally ready for whatever it is we need to do with Exchange. In this example, I'm going to poke around in the public folders and gather information for the day's calendar appointments. I'll also use a regular expression to find the organizer's full name; the full string contains their name and email address, which might not be suitable for what you're trying to display.


/// 
/// Find today's appointments in the public folder calendar and print the results.
/// 

public void RunQuery()
{
    string uri = server + path;
    HttpWebRequest request;
    WebResponse response;
    byte[] bytes;

    string start = DateTime.Today.ToString( "yyyy/MM/dd" );
    string end = DateTime.Today.ToString( "yyyy/MM/dd" );

    // Note that deep traversals don't work on public folders. In other words, if you
    // need to dig deeper you'll need to split your query into multiple requests.

    string format =
        @"
            
                
                    SELECT
                        ""urn:schemas:calendar:dtstart"", ""urn:schemas:calendar:dtend"",
                        ""urn:schemas:httpmail:subject"", ""urn:schemas:calendar:organizer"",
                        ""DAV:parentname""
                    FROM
                        Scope('SHALLOW TRAVERSAL OF ""{0}""')
                    WHERE
                        NOT ""urn:schemas:calendar:instancetype"" = 1
                        AND ""DAV:contentclass"" = 'urn:content-classes:appointment'
                        AND ""urn:schemas:calendar:dtstart"" > '{1}'
                        AND ""urn:schemas:calendar:dtend"" < '{2}'
                    
            ";

    bytes = Encoding.UTF8.GetBytes( String.Format( format, uri, start, end ) );

    // Use the authorization cookies we stored in the authentication method.

    request = (HttpWebRequest)HttpWebRequest.Create( uri );
    request.CookieContainer = authCookies;
    request.Method = "SEARCH";
    request.ContentLength = bytes.Length;
    request.ContentType = "text/xml";

    using ( Stream requestStream = request.GetRequestStream() )
    {
        requestStream.Write( bytes, 0, bytes.Length );
        requestStream.Close();
    }

    response = (HttpWebResponse)request.GetResponse();

    using ( Stream responseStream = response.GetResponseStream() )
    {
        // Parse the XML response to find the data we need.

        XmlDocument document = new XmlDocument();
        document.Load( responseStream );

        XmlNodeList subjectNodes = document.GetElementsByTagName( "e:subject" );
        XmlNodeList locationNodes = document.GetElementsByTagName( "a:parentname" );
        XmlNodeList startTimeNodes = document.GetElementsByTagName( "d:dtstart" );
        XmlNodeList endTimeNodes = document.GetElementsByTagName( "d:dtend" );
        XmlNodeList organizerNodes = document.GetElementsByTagName( "d:organizer" );

        for ( int index = 0; index < subjectNodes.Count; index++ )
        {
            string subject = subjectNodes[index].InnerText;
            string organizer = organizerNodes[index].InnerText;
            string location = ParentName( locationNodes[index].InnerText );
            DateTime startTime = DateTime.Parse( startTimeNodes[index].InnerText );
            DateTime endTime = DateTime.Parse( endTimeNodes[index].InnerText );

            // Use a regex to get just the user's first and last names. Note that
            // some appointments may not have a valid user name.

            string pattern = @"""(?.*?)""";
            Regex regex = new Regex( pattern, RegexOptions.None );
            Match matchedText = regex.Match( organizer );

            if ( matchedText.Success && matchedText.Groups["name"] != null )
                organizer = matchedText.Groups["name"].Value;

            // Print the results to the console.

            Console.WriteLine( "{0} - {1}: {2}", startTime.ToShortTimeString(), endTime.ToShortTimeString(), subject );
            Console.WriteLine( "{0} ({1})", location, organizer );
            Console.WriteLine();
        }

    }

    response.Close();
}

Just as before, we're making an HTTP request and reading back the response. The body of the request is XML markup that contains the Exchange data store query. The query itself is similar (both in structure and power) to SQL, so you should feel right at home if you've worked with databases before. It's possible to use a deep traversal or specify multiple folders in the FROM clause, as long as you're not looking in the public folders. If you are, you'll need to make multiple WebDAV requests to get the data you need.

The response is also XML, and since .NET has excellent XML support, we don't have to do much work to parse it. As I mentioned before, I used a regular expression to change one of the attributes, but that part is really optional. The format of both the request query and response is complex (to say the least), but everything you need should be in MSDN. I've included a few links at the end of the article to get you started.

Finishing Up

All that's left now is to run the query! I'll also do a little error handling here, and catch the exceptions I'm likely to run into.


static void Main( string[] args )
{
    try
    {
        WebDAVRequest request = new WebDAVRequest();
        request.Authenticate();
        request.RunQuery();
    }
    catch ( SecurityException e )
    {
        Console.WriteLine( "Security Exception" );
        Console.WriteLine( "   Msg: " + e.Message );
        Console.WriteLine( "   Note: The application may not be trusted if run from a network share." );
    }
    catch ( AuthenticationException e )
    {
        Console.WriteLine( "Authentication Exception, are you using a valid login?" );
        Console.WriteLine( "   Msg: " + e.Message );
        Console.WriteLine( "   Note: You must use a valid login / password for authentication." );
    }
    catch ( WebException e )
    {
        Console.WriteLine( "Web Exception" );
        Console.WriteLine( "   Status: " + e.Status );
        Console.WriteLine( "   Reponse: " + e.Response );
        Console.WriteLine( "   Msg: " + e.Message );
    }
    catch ( Exception e )
    {
        Console.WriteLine( "Unknown Exception" );
        Console.WriteLine( "   Msg: " + e.Message );
    }
}

How you integrate this in your own application is up to you, and ultimately depends what it is you're trying to accomplish. One of the things I like about .NET is how flexible and reusable it often is. In my case, I put the Exchange handling code and related classes in its own class library, which is imported into the ASP .NET webapp that displays the data to the user. When it's time to update the library, or create a different ASP .NET project that uses the code, all I have to do is copy a single .dll into the project.

Here are a few URLs you might need as you go.

Searching Calendar Folders with WebDAV
Exchange Store Key Tasks
Exchange Programming Technologies

There are 38 comments in this article:

  1. 2/11/2006dan says:

    Great article. I’ve spent a few hours sifting through sites describing different techniques (some of them deprecated) to get similar task achieved and ended up using .NET with webdav as well.

    My follow-up question is: for Exchange contact information, how do you go about retrieval of all information regarding specific contact. I’ve been able to get the list of contacts using SEARCH method, however I have not been able to find good resource that points out how to retrieve all information regarding each contact in the contacts folder.

    Do you have any pointers in this respect?

  2. 4/11/2006Marc Charbonneau says:

    I’m glad you found it useful Dan. I’ve only dealt with calendars in my applications, but you can find more about the contact schema here:

    urn:schemas:contacts: Namespace

  3. 6/11/2006Kaminda says:

    It is really a very usefull article. Thanks for sharing this with us.
    In my problem I want to access the inbox to get new mails and process the information inside. Can you please help me with the query section. It will be a great help.

  4. 10/11/2006Confluence: Development says:

    Exchange OWA…

    Using From Java…

  5. 11/12/2006Julio Izquierdo says:

    I wrote similar code using the CredentialCache.DefaultCredentials. It works locally but not on my Dev server. Any Ideas?
    My web.config is set to impersonate and directory security is set to Windows Integration only.
    Thanks!

    -Julio

  6. 31/01/2007Community Blogs says:

    How do I access my Outlook contacts from my web application?…

    Question How do I access my Outlook contacts from my web application? Short Answer You don’t, well at…

  7. 21/03/2007Carsten says:

    Great article, it helped a lot. Thank you!

  8. 4/04/2007mikk says:

    Thanks a lot!

  9. 12/04/2007Vinoth says:

    Hi
    your code is good.REally Helpful…..
    Can u help me?
    if this is the case…..
    I have to hit a Https site? can it be done?
    getting back the page content by sending post data, say username and pwd

  10. 14/05/2007Ron says:

    Great article, thanks so much. I am having two problems with the code: First, to derive location you use a function named ParentName, but when I build I get an unidentified error, am I missing a reference or something?

    Second, I’m trying to get a particular user’s calendar. What is the folder path? Is it based on the username or something like that? If anyone knows, please mail me: ron [at] ronaldphillips [dot] com Thanks!

  11. 15/05/2007Marc Charbonneau says:

    The ParentName function is my mistake; it looks like I left that in by accident when I was writing this post. From what I remember, it just does some formatting to the calendar’s name, so you can remove it or replace it with your own code if it’s an attribute you need.

    For a user’s calendar you’re correct, the path is based on the username. You can actually just open up OWA and look at the URL in your web browser to help figure out what you need. Take a look at the links at the end of the post too, I think those will help you.

  12. 16/08/2007Arsen Mkrtchyan says:

    Good and useful article but when i try to get request from server i get exception WebException The underlying connection was closed: The connection was closed unexpectedly. any ideas why i get this?

  13. 23/08/2007Rajesh says:

    i have a prob with code.

    im getting error “NotSupportedException: This stream does not support seek operations” in line

    Stream stream = request.GetRequestStream()

    tell me its solution.

    I got some help from
    http://msdn2.microsoft.com/en-us/library/system.io.stream.aspx
    but its not enough to solve the prob.

    thnks in advance.

  14. 19/09/2007Alex says:

    Hi Marc and everyone,

    Great article, Marc. Don’t know if you’re still here but wondering if you or indeed anyone could help me on this.

    I am using your code but I am not able to get pass the authentication stage, it’s throwing an AuthenticationException/Login failed. I am really new to all this and don’t know what I am doing wrong. I have set up SSL and Forms Based Authentication and I am able to log in to the OWA through a browser using the Domain\Username and Password. But when I try substituting the same Domain\Username (or just the Username by itself) and the password into the code, it doesn’t work.

    Any help will be greatly appreciated, thank you.

    Alex

  15. 20/09/2007Alex says:

    Hi, it’s me again.

    Just a slight update if anyone’s reading this. I am setting the ‘server’ to be https://exchange2000/ but in the browser, this returns a “Under Construction” page. I actually have to change the url in the browser to https://exchange2000/exchange in order to be redirected to the OWA login page. I then tried using https://exchange2000/exchange as the ‘server’ in the code but I can’t even connect then. Is there something or setting that I could have wrong?

    Again, any help will be greatly appreciated, thank you.

    Alex

  16. 16/10/2007leena says:

    Hi Marc and everybody,

    I was successfully able to run the program and get the output wherein only the start and end time of the meetings and the subject gets displayed.

    when the related lines of the organizer were commented the code worked.

    what could be the reason for the value of the organizer not getting dispalyed?

    I need some help in modifying the code to get even the organizer and attendees names and to display them.

    It would be very helpful if anybody suggests something.

    leena

  17. 17/10/2007anna says:

    hi,

    good article here. i just have a question, hope you could at least give me and idea why, after being authenticated I am always getting a (400) bad request error, on the “HttpWebRequest.Create(uri);” line.

    any help will be greatly appreciated. thanks!

  18. 14/12/2007Alexander says:

    Hello,
    I need your help with Exchange2007.
    How can I get(find) the user contacts(not my local contacts as I found in the sample http://puzzleware.net/blogs/archive/2007/01/30/How-do-I-access-my-Outlook-contacts-from-my-web-application_3F00_.aspx)
    with search criteria using Exchange2007 WebDav or EWS, because in Exchange2007 WebDav I could not find the function [galfind] that present in Exchange2003 version.

  19. 14/12/2007Alexander says:

    Hello guys again.

    Could you help me where can I find the good(perfect, detailed) documentation and samples to Exchange2007 WebDav and EWS programming. I could not find only one book of Microsoft Press(Exchange2007 Web Services), I have booked it, but would get it only in the end of December this year. In Exchange2007 SDK was very bad documented and the samples are very poor.

  20. 20/12/2007Satish says:

    Please help me out.
    I am trying to access an exchange Server as specified in the above article. But I am getting a Web Exception “The Remote Server returned an error (401) Unauthourised” with the Status message Protocol Error. Googling cant help me in this aspect. My Main problem was that I am accessing an Exchange Sever that is in a Seperate domain from my Environment. I am passing the Exchange User Credentials in the form “domain\ExchangeUser”.Am I doing correct or I need to do some configuration at the Exchange Server side so as to make my program work.?

    Thanks,
    Satish

  21. 28/12/2007mikkell says:

    I have the same problem as you Satish – please give sound if you find a solution.

  22. 9/01/2008Mike Fagan says:

    I am trying to use .NET, c# and webdav to create appointments and send meeting requests from my ASP 2.0 web application when people pick a class to attend. I have tried many different things and have been partially successful. I would love to send you my code I have for you to look over, or if you could send me a sample on how to do that I would appreciate it alot! Thanks in advance for your help!

  23. 21/01/2008Wai says:

    I have the problem
    The remote server returned an error: (440) Login Timeout.
    when use on exchange 2007, can anybody help me out what’s the problem?

  24. 22/01/2008Anonymous says:

    like Satish & Mikkell, I am getting a Web Exception “The Remote Server returned an error (401) Unauthourised” with the Status message Protocol Error at

    HttpWebResponse response = (HttpWebResponse)request.GetResponse

    I used following request option to use current user’s credentials – and it worked fine
    request.UseDefaultCredentials = true;

    but where am i going wrong when using explicite username?

  25. 29/01/2008AlexD says:

    Hi.
    I’m doing WebDAV requests on a server that now has Forms authentication enabled.I switched from NT credentials to the cookie usage(similar to what you described in your post).
    The problem is that although I have the cookies from the initial request and I add them correctly in the Cookie container I get the bloody 440 Login timeout.
    Any suggestions ?

  26. 30/01/2008Wai says:

    Sorry it’s me again, I find that only 1 cookie is returned which the name is “UserContext” in Exchange 2007 insteads of 2 cookies which the name is “sessionid” and “cadata” in exchange 2003, anyone know what is the problem? Thanks.

  27. 31/01/2008JonnyO says:

    Great article !!!

    Thanx from JO.

  28. 11/04/2008KoenW says:

    Great Article!! Helped me alot.
    Seeing the timespan between the first comment and the last (before me: 2008/01/31)
    There is still a big need in Exchange webdav coding resources!
    Anyway, you’re article helped me alot and combines alot of the resources I’ve found in one complete example!

  29. 28/04/2008PSnows says:

    Hi!

    How can I create a E-mail message on a user Mailbox, as a draft that he may send after, using C# and WebDav.

    I’ve crawling around Google all the afternoon and I found nothing that can solve this issue.

    Thanx in advance for any help.

    Best Regards,

    Peter

  30. 26/09/2008siddharth says:

    nice article but now i want ,retrieve all appointments listed in inbox.

    thanks

  31. 1/10/2008Nick says:

    Hi, Great Article!

    I’ve had to make a few modifications to work on .NET 3.0, (Visual Studio 2008). I now get the following error: (440) Login Timeout.

    I am trying this against exchange 2007. It seems its not storing the cookie perhaps? When I step through the code it adds 2 cookies.

    I had to change it to: CookieContainer Cookies = new CookieContainer();

    When I display the output in the console on each cookie.add line, the name are sessionid and cdata. Which are correct.

    Can anyone help??

    Thanks!

    Nick

  32. 1/10/2008Nick says:

    Hi, me again!

    I mean i’m running this against Exchange 2003!!

    Thanks,

    Nick

  33. 2/10/2008Johan O says:

    I’ve read alot of articles and have been having alot of problems getting it to work. But today I got it working after reading this article. I got it working in Visual Studio 2008 using an Exchange 2003 server.

    One of the biggest problems i’ve been having was understanding how to set the path to what I want.

    It works like this:

    https:///exchange//

    where can be inbox, calendar, and so on.

    Now the second problem is that there is an error in this article. The author has set the wrong name of the cookie variable which made me get the error message login timeout.

    I also uncommented the xml part and made it just show the response in a single messagebox. I also created a windows forms application and added a button for testing the code. Here is my code, just paste it into a new form and change the server name and username and password:

    I also created an example query which finds and outputs all the mails in your mailbox.

    using System;
    using System.IO;
    using System.Xml;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.Net.Security;
    using System.Security.Cryptography.X509Certificates;
    using System.Security.Authentication;
    using System.Text.RegularExpressions;
    using System.Windows.Forms;
    using System.Security;

    namespace ExchangeTest6
    {
    public partial class Form1 : Form
    {

    static void RunExampleQuery()
    {
    try
    {
    WebDAVRequest request = new WebDAVRequest();
    request.Authenticate();
    request.RunQuery();
    }
    catch (SecurityException e)
    {
    Console.WriteLine(“Security Exception”);
    Console.WriteLine(” Msg: ” + e.Message);
    Console.WriteLine(” Note: The application may not be trusted if run from a network share.”);

    MessageBox.Show(e.Message);
    }
    catch (AuthenticationException e)
    {
    Console.WriteLine(“Authentication Exception, are you using a valid login?”);
    Console.WriteLine(” Msg: ” + e.Message);
    Console.WriteLine(” Note: You must use a valid login / password for authentication.”);

    MessageBox.Show(e.Message);
    }
    catch (WebException e)
    {
    Console.WriteLine(“Web Exception”);
    Console.WriteLine(” Status: ” + e.Status);
    Console.WriteLine(” Reponse: ” + e.Response);
    Console.WriteLine(” Msg: ” + e.Message);

    MessageBox.Show(e.Message);
    }
    catch (Exception e)
    {
    Console.WriteLine(“Unknown Exception”);
    Console.WriteLine(” Msg: ” + e.Message);

    MessageBox.Show(e.Message);
    }
    }

    public Form1()
    {
    InitializeComponent();

    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void button1_Click(object sender, EventArgs e)
    {
    RunExampleQuery();
    }

    }

    public class WebDAVRequest
    {

    private static string server = “https://servername”;
    private static string path = “/exchange/username/calendar”;
    private static string username = “username”;
    private static string password = “password”;

    ///
    /// Add code here to check the server certificate, if you think it’s necessary. Note that this
    /// will only be called once when the application is first started.
    ///

    protected bool CheckCert(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
    return true;
    }

    ///
    /// Default WebDAVRequest constructor. Set the certificate callback here.
    ///

    public WebDAVRequest()
    {
    ServicePointManager.ServerCertificateValidationCallback += CheckCert;
    }

    ///
    /// Default WebDAVRequest constructor. Set the certificate callback here.
    ///

    ///
    /// Authenticate against the Exchange server and store the authorization cookie so we can use
    /// it for future WebDAV requests.
    ///
    CookieContainer cookies;

    public void Authenticate()
    {
    string authURI = server + “/exchweb/bin/auth/owaauth.dll”;

    // Create the web request body:

    string body = string.Format(“destination={0}&username={1}&password={2}”, server + path, username, password);
    byte[] bytes = Encoding.UTF8.GetBytes(body);

    // Create the web request:

    HttpWebRequest request = (HttpWebRequest)System.Net.WebRequest.Create(authURI);
    request.Method = “POST”;
    request.ContentType = “application/x-www-form-urlencoded”;
    request.CookieContainer = new CookieContainer();
    request.ContentLength = bytes.Length;

    // Create the web request content stream:

    using (Stream stream = request.GetRequestStream())
    {
    stream.Write(bytes, 0, bytes.Length);
    stream.Close();
    }

    // Get the response & store the authentication cookies:

    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    if (response.Cookies.Count ‘{1}’
    // AND “”urn:schemas:calendar:dtend”" < ‘{2}’
    //
    // “;

    string sUri = “http://server01/exchange/jotterud/inbox”;

    string format =
    “” +
    “” +
    “SELECT \”DAV:displayname\” ” +
    “FROM SCOPE(‘SHALLOW TRAVERSAL OF \”" + sUri + “\”‘) ” +
    “WHERE \”DAV:isfolder\” = false” +
    “” +
    “”;

    bytes = Encoding.UTF8.GetBytes(String.Format(format, uri, start, end));

    // Use the authorization cookies we stored in the authentication method.

    request = (HttpWebRequest)HttpWebRequest.Create(uri);
    request.CookieContainer = cookies; //authCookies;
    request.Method = “SEARCH”;
    request.ContentLength = bytes.Length;
    request.ContentType = “text/xml”;

    using (Stream requestStream = request.GetRequestStream())
    {
    requestStream.Write(bytes, 0, bytes.Length);
    requestStream.Close();
    }

    response = (HttpWebResponse)request.GetResponse();

    Stream responseStream = response.GetResponseStream();

    //Read the Response Steam;
    StreamReader sr = new StreamReader(responseStream);
    String sText = sr.ReadToEnd();

    MessageBox.Show(sText);

    //using (Stream responseStream = response.GetResponseStream())
    //{
    // // Parse the XML response to find the data we need.

    // XmlDocument document = new XmlDocument();
    // document.Load(responseStream);

    // XmlNodeList subjectNodes = document.GetElementsByTagName(“e:subject”);
    // XmlNodeList locationNodes = document.GetElementsByTagName(“a:parentname”);
    // XmlNodeList startTimeNodes = document.GetElementsByTagName(“d:dtstart”);
    // XmlNodeList endTimeNodes = document.GetElementsByTagName(“d:dtend”);
    // XmlNodeList organizerNodes = document.GetElementsByTagName(“d:organizer”);

    // for (int index = 0; index < subjectNodes.Count; index++)
    // {
    // string subject = subjectNodes[index].InnerText;
    // string organizer = organizerNodes[index].InnerText;
    // string location = locationNodes[index].InnerText; // ParentName(locationNodes[index].InnerText);
    // DateTime startTime = DateTime.Parse(startTimeNodes[index].InnerText);
    // DateTime endTime = DateTime.Parse(endTimeNodes[index].InnerText);

    // // Use a regex to get just the user’s first and last names. Note that
    // // some appointments may not have a valid user name.

    // string pattern = @”"”(?.*?)”"”;
    // Regex regex = new Regex(pattern, RegexOptions.None);
    // Match matchedText = regex.Match(organizer);

    // if (matchedText.Success && matchedText.Groups["name"] != null)
    // organizer = matchedText.Groups["name"].Value;

    // // Print the results to the console.

    // Console.WriteLine(“{0} – {1}: {2}”, startTime.ToShortTimeString(), endTime.ToShortTimeString(), subject);
    // Console.WriteLine(“{0} ({1})”, location, organizer);
    // Console.WriteLine();
    // }

    //}

    response.Close();
    }
    }

    }

  34. 2/10/2008Johan O says:

    In the above post the url was parsed… should be

    —————-

    It works like this:

    https://server-name/exchange/username/type

  35. 3/10/2008Nick says:

    Is it correct that authCookies; is being set to null and never being set a value?

    Its storing the cookies ok but failing when it trys to call them. I believe because authCookies is null? has anyone had a simular problem?

  36. 7/10/2008werutzb says:

    Hi!

    I would like extend my SQL capabilities.
    I red so many SQL books and would like to
    get more about SQL for my work as oracle database manager.

    What can you recommend?

    Thanks,
    Werutz

  37. 9/10/2008Trevor says:

    This is a great article, I just hope it is still being updated.

    My question is whether or not anyone solved the 401 error that many people reported in their responses.

    I have the same error when doing WebDAV against a Exch 2k3 server, and would really like a resolution.

  38. 18/01/2009login OWA of Exchange 2007 using .NET2003 | keyongtech says:

    [...] OWA of Exchange 2007 using .NET2003 Dear all, I’ve been using the code http://blog.downtownsoftwarehouse.co…change-server/ to write a .NET C# program to login OWA of 2003 and it works fine, however, when I port the [...]