Using Streaming Subscriptions in Exchange 2010

Last modified: September 23, 2010

Applies to: Exchange Server 2007 | Exchange Server 2010

Exchange Web Services provides a streaming subscription that enables client applications to discover events that occur in the Exchange store. The streaming subscription is similar to both a pull and a push subscription. The application submits a GetStreamingEvents Operation request by using the subscription identifier, similar to a pull subscription. Then, the server sends event notifications to the client application, similar to a push subscription.

Using streaming notifications involves the following steps:

  • Creating the binding and setting the credentials

  • Creating a streaming subscription

  • Getting event notifications

This topic includes the procedures for using streaming notifications.

To create the binding and set the credentials

  1. Create the binding that is to be used by the Subscribe Operation and the GetStreamingEvents Operation. For more information, see Setting Up the ExchangeServiceBinding Proxy Class in Exchange 2010.

  2. Identify the URL of the Client Access server and the user credentials that are to be used to send the requests.

To create a streaming subscription

  1. Create a new Subscribe Operation request.

  2. Identify the subscription type.

  3. Identify the folders to monitor for events.

  4. Identify the events to monitor for the subscription.

  5. Send the request and receive the response. The response includes the subscription identifier.

To get event notifications

  1. Create a new GetStreamingEvents Operation request.

  2. Use the subscription ID that is returned in the Subscribe Operation response.

  3. Send the GetStreamingEvents request and receive the response. Each response includes information about one or more events.

    Note

    If no store events have occurred since the last GetStreamingEvents request, a status event is returned.

Example

The following example from a console application shows how to create a streaming subscription and output the number of notification events in the response.

        static void SetStreamingNotifications(ExchangeServiceBinding esb)
        {
            // Subscribe to streaming notifications on the Inbox folder, and only listen
            // to new mail, created, and deleted events.
            SubscribeType subscribeType = new SubscribeType();
            StreamingSubscriptionRequestType streamingRequest = new StreamingSubscriptionRequestType();
            streamingRequest.EventTypes = new NotificationEventTypeType[] 
            { 
               NotificationEventTypeType.NewMailEvent, 
               NotificationEventTypeType.CreatedEvent, 
               NotificationEventTypeType.DeletedEvent
            };
            streamingRequest.SubscribeToAllFolders = true;
            streamingRequest.SubscribeToAllFoldersSpecified = true;
            subscribeType.Item = streamingRequest;

            SubscribeResponseType response = esb.Subscribe(subscribeType);

            // Create the XML file for the request.
            CreateXmlMessageTextFile(subscribeType, response);

            // Get the subscription ID from the response.
            SubscribeResponseMessageType subscribeResponseMessage = response.ResponseMessages.Items[0] as SubscribeResponseMessageType;
            String subscriptionid = subscribeResponseMessage.SubscriptionId;
        }

After the subscription ID is retrieved, use an asynchronous Web request and response to submit the GetStreamingEvents Operation request and wait for responses.

The following example shows how a GetStreamingEvents request is generated. The subscription ID is passed into the routine and a StringBuilder object is used to store the generated XML request.

static HttpWebRequest GenerateStreamingRequest(string subscriptionid)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://CAS01.contoso.com/EWS/Exchange.asmx");
            // Set Credentials.
            request.Credentials = new NetworkCredential("User1", "pass@word1");

            // Prepare the SOAP string with the appropriate subscription ID.
            StringBuilder SoapStr = new StringBuilder();
            SoapStr.Append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
            SoapStr.Append(" xmlns:m=\"https://schemas.microsoft.com/exchange/services/2006/messages\"");
            SoapStr.Append(" xmlns:t=\"https://schemas.microsoft.com/exchange/services/2006/types\"");
            SoapStr.Append(" xmlns:soap=\"https://schemas.xmlsoap.org/soap/envelope/\">\n");
            SoapStr.Append("  <soap:Header>\n");
            SoapStr.Append("    <t:RequestServerVersion Version=\"Exchange2010_SP1\" />\n");
            SoapStr.Append("  </soap:Header>\n");
            SoapStr.Append("  <soap:Body>\n");
            SoapStr.Append("    <m:GetStreamingEvents>\n");
            SoapStr.Append("      <m:SubscriptionIds>\n");
            SoapStr.Append("        <t:SubscriptionId>" + subscriptionid + "</t:SubscriptionId>\n");
            SoapStr.Append("      </m:SubscriptionIds>\n");
            SoapStr.Append("      <m:ConnectionTimeout>30</m:ConnectionTimeout>\n");
            SoapStr.Append("    </m:GetStreamingEvents>\n");
            SoapStr.Append("  </soap:Body>\n");
            SoapStr.Append("</soap:Envelope>\n");

            request.ContentType = "text/xml; charset=\"utf-8\"";
            request.Accept = "text/xml";
            request.Method = "POST";

            byte[] bytes = Encoding.UTF8.GetBytes(SoapStr.ToString());
            request.ContentLength = bytes.Length;

            using (Stream stm = request.GetRequestStream())
            {
                using (StreamWriter stmw = new StreamWriter(stm))
                {
                    stmw.Write(SoapStr.ToString());
                }
            }
            return request;
        }

The following example shows how to parse the response that is returned by the server. In this example, the XML is searched by using XPath to find all the nodes for specified events.

static void GetStreamingResponse(HttpWebResponse streamingresponse)
     {
            String result = "";
            using (streamingresponse)
            {
                StreamReader reader = new StreamReader(streamingresponse.GetResponseStream());
                result = reader.ReadToEnd();
            }

            // The following wrapper is needed for a multiple node error.
            result = "<MyStreamingResponse>" + result + "</MyStreamingResponse>";
            // Display the result - the returned text.
            Console.WriteLine("\n" + result);
            
            // Load the result into an XML document and set the root node.            
            XmlDocument doc = new XmlDocument();
            doc.Load(new StringReader(result));
            XmlNode root = doc.DocumentElement;
            // Add the namespace.
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
            nsmgr.AddNamespace("t", "https://schemas.microsoft.com/exchange/services/2006/types");
            
            // Using Xpath, search for the subscribed events.
            XmlNodeList nodeList1 = root.SelectNodes("//t:NewMailEvent", nsmgr);
            Console.WriteLine("NewMailEvents= " + nodeList1.Count.ToString());
            XmlNodeList nodeList2 = root.SelectNodes("//t:DeletedEvent", nsmgr);
            Console.WriteLine("DeletedEvents= " + nodeList2.Count.ToString());
            XmlNodeList nodeList3 = root.SelectNodes("//t:CreatedEvent", nsmgr);
            Console.WriteLine("CreatedEvents= " + nodeList3.Count.ToString());
     }

You can also use the XmlNodeList object to step through the collection of nodes to read additional information about each of the returned events.