Microsoft® Exchange ActiveSync® is a collection of protocols that enables mobile devices to synchronize and exchange messaging objects such as email, contacts, or calendar items with a server. The Microsoft Exchange Server protocol documentation includes a number of Exchange ActiveSync protocol specifications that provide the information you need to implement a fully-functional Exchange ActiveSync client or server. This article is the first in a series of articles that will provide detailed guidance for implementing an Exchange ActiveSync client by using the Exchange ActiveSync protocols. In this article, we will examine the process of establishing the basic transport mechanism when implementing an Exchange ActiveSync client. Our discussion will leverage information in the following Exchange Server protocol specifications:

The complete set of Exchange ActiveSync protocol specifications is available in the MSDN Library. If you’re new to using the Exchange Server Open Specifications, I’d highly recommend that you review Exploring the Microsoft Exchange Server Open Specifications for information about how the specifications are named and structured, and for tips that’ll help you derive maximum benefit from using the specifications.

While the Exchange Server protocols can be implemented with any development tools and on any platform, this sample relies on the following items.

Item

Tool/Platform

Development environment

Microsoft® Visual Studio® 2010 Professional (using C#)

Platform

Microsoft® .NET Framework version 4.0

Exchange ActiveSync server

Microsoft® Exchange Server 2010 Service Pack 1 (SP1)

Since we are using Exchange Server 2010 SP1 as the ActiveSync server, we will focus on Exchange ActiveSync version 14.1. This sample will not include any special handling for previous Exchange ActiveSync versions.

The client generates an XML payload based on the Exchange ActiveSync command and passes the payload to an implementation of the ActiveSync WBXML protocol for encoding.

The ActiveSync WBXML protocol implementation initializes a WBXML implementation with the necessary information to encode Exchange ActiveSync XML payloads. The XML payload is passed to the WBXML implementation, and a WBXML payload is generated.

The client passes the WBXML payload to an implementation of the ActiveSync HTTP protocol.

The ActiveSync HTTP protocol implementation adds the WBXML payload to an HTTP request, generates a URI, and sets appropriate headers. The HTTP request is sent to the server.

The server response comes back to the ActiveSync HTTP protocol implementation. The WBXML payload is extracted from the response and passed back to the client.

The client passes the WBXML payload to the ActiveSync WBXML implementation for decoding.

The ActiveSync WBXML implementation initializes a WBXML implementation with the necessary information to decode ActiveSync WBXML payloads. The WBXML payload is passed to the WBXML implementation, and an XML payload is generated.

Now that we understand the basic process flow of an Exchange ActiveSync implementation, let’s explore what’s required to establish the basic transport mechanism for Exchange ActiveSync. To establish the transport mechanism (by using the ActiveSync HTTP protocol and the ActiveSync WBXML protocol), we will need to implement both HTTP and WBXML. Fortunately, the .NET Framework provides an HTTP implementation in the System.Net namespace that we can use. However, we are not so fortunate for WBXML—we’ll need to build the WBXML implementation ourselves.

Once WBXML is implemented, implementing the ActiveSync WBXML protocol is fairly straightforward. The protocol consists of a set of WBXML code pages, one for each XML namespace that is defined by the Exchange ActiveSync protocols.

This mapping of namespaces to code pages actually imposes an additional requirement on the implementation. Code pages aren't required by the WBXML specification to map to namespaces, but the ActiveSync WBXML protocol requires a namespace-to-code page mapping. It is important to ensure that the parser can determine what namespace an XML tag belongs to so that it can use the appropriate code page.

The ASWBXML, ASWBXMLByteQueue, and ASWBXMLCodePage classes (see the "Sample source" section later in this article) comprise this sample's implementation of the ActiveSync WBXML protocol.

The ability to send an HTTP OPTIONS method and parse the headers in the response.

The ability to send an HTTP POST method and parse the response.

The ability to generate a URI based on the Exchange ActiveSync command being executed. This URI may be in a plain-text format, or may be a base64-encoded representation of a specific binary format that encapsulates parameters for the Exchange ActiveSync command.

The ASOptionsRequest, ASOptionsResponse, ASCommandRequest, ASCommandResponse, and EncodedRequest classes (see the "Sample source" section later in this article) comprise the sample's implementation of the ActiveSync HTTP protocol.

The sample application code (see the "Sample source" section later in this article) consists of several classes that can be used together to implement the ActiveSync WBXML protocol and the ActiveSync HTTP protocol. Let's take a look at the classes implemented in the sample.

Class name

Description

ASWBXML

This class contains all of the XML-to-WBXML and WBXML-to-XML functionality. It also contains the WBXML code pages defined in the ActiveSync WBXML protocol.

ASWBXMLByteQueue

This class contains functionality to manage the bytes that comprise WBXML data. It is used by the ASWBXML class during WBXML-to-XML decoding.

ASWBXMLCodePage

This class contains the functionality to do XML tag-to-WBXML token lookups and WBXML token-to-XML tag lookups. It is used by the ASWBXML class during encoding and decoding.

ASOptionsRequest

This class contains the functionality to query the server using an HTTP OPTIONS method and generate an instance of the ASOptionResponse class.

ASOptionsResponse

This class contains the functionality to parse an HTTP OPTIONS method response and extract the relevant information, such as supported Exchange ActiveSync versions.

ASCommandRequest

This class contains the functionality to generate and send a properly formatted HTTP POST method that contains an Exchange ActiveSync command, and generate an instance of the ASCommandResponse class.

ASCommandResponse

This class contains the functionality to parse an HTTP POST method response that contains the response to an Exchange ActiveSync command.

EncodedRequest

This class contains the functionality to generate a relative URI for an HTTP POST method that contains an Exchange ActiveSync command. It is used by the ASCommandRequest class.

Now, let's take a closer look at the implementation of each piece. For more information, the full source code for each class is listed in the "Sample source" section later in this article.

ActiveSync WBXML

Let's start with the ActiveSync WBXML protocol. Our approach is a single class (ASWBXML) that acts as an encoder and decoder. To accommodate this approach, our class has 4 public functions: LoadXml, GetXml, LoadBytes, and GetBytes. The LoadXml and GetXml functions load or return a string containing an XML document. The LoadBytes and GetBytes functions load or return a byte array containing WBXML bytes.

Internally, the class uses the XmlDocument class from the System.Xml namespace to manage all XML operations. It also needs to be able to handle binary WBXML data and to perform lookups against the WBXML code pages specified in the ActiveSync WBXML protocol.

Parsing binary WBXML data requires that the data be read byte-by-byte, with no need to jump forward or backward in the data (essentially a first-in, first-out scenario). This makes the Queue class in the System.Collections.Generic namespace a good candidate for handling our binary data in the WBXML-to-XML scenario. For most cases, the Dequeue function will suit our needs. However, WBXML uses a slightly more complicated encoding for integers (see "Multi-byte Integers" in WAP Binary XML Content Format). So our approach is to create the ASWBXMLByteQueue class, which inherits from the Queue class and adds two functions: DequeueMultibyteInt and DequeueString.

In order to perform WBXML code page lookups, we create the ASWBXMLCodePage class. This class represents a single code page and provides lookup functionality by using the Dictionary class from the System.Collections.Generic namespace. Because we need to be able to do lookups both ways (token-to-tag and tag-to-token), the ASWBXMLCodePage class actually has two instances of the Dictionary class. It also has two string properties, Namespace and Xmlns. Their purpose is to identify the XML namespace that corresponds to the code page. The ASWBXML class contains an array of ASWBXMLCodePage classes that correspond to the code pages in the ActiveSync WBXML protocol.

ActiveSync HTTP

Now that we are able to encode our XML payloads, let's turn our attention to actually sending them. We'll start by implementing two classes to handle the OPTIONS method: ASOptionsRequest and ASOptionsResponse. The ASOptionsRequest has one function: GetOptions. This function uses the HttpWebRequest class in the System.Net namespace to send an OPTIONS method request to the server. It passes the HttpWebResponse class returned to the ASOptionsResponse class, which parses the headers for the MS-ASProtocolCommands and MS-ASProtocolVersions headers.

Next, we implement two classes for the POST method: ASCommandRequest and ASCommandResponse. The ASCommandRequest class exposes a number of properties that must be set to control which Exchange ActiveSync command is used and to set parameters. It also exposes properties allowing the caller to set an XML payload or a pre-encoded WBXML payload. Internally, it uses the ASWBXML class to encode XML payloads. It exposes one public function, GetResponse, which returns an ASCommandResponse class.

The ASCommandResponse class parses an HttpWebResponse class and uses the ASWBXML class to decode the WBXML payload.

Finally, the ASCommandRequest class needs to be able to create base64-encoded URIs. Using base64-encoded URIs saves a bit of data on the wire, since the URI itself tends to be a bit shorter, and a number of headers don't need to be transmitted since their values are included in the URI itself. To do this, we'll implement the EncodedRequest class. This class exposes the fields of the Base64 Encoded Query Value structure defined in the ActiveSync HTTP protocol as properties. It also exposes the function GetBase64EncodedString which returns the encoded URI based on the values of the properties.

The following example shows how to use the ASOptionsRequest and ASCommandRequest classes to send requests to the server. In this example, the client sends a Provision command to the server and outputs the response.

Now that we've implemented the ActiveSync WBXML protocol and the ActiveSync HTTP protocol, we have the transport in place to begin implementing additional Exchange ActiveSync protocols. Since servers often require provisioning before they allow other Exchange ActiveSync operations, a logical next step is to implement the ActiveSync Provisioning protocol. The next article in this series will walk through an ActiveSync Provisioning protocol implementation, so stay tuned!