Search code examples
c#exchangewebservicesews-managed-api

Exception when subscribing to exchange streaming notifications


I'm currently working on a project that has me integrating with Exchange. One of the requirements is to monitor mailboxes for new incoming messages and I thought that leveraging a streaming notifications would be a good idea.

I wrote a sample application to get familiar with how to leverage streaming notifications, however I am encountering the following error: The expected XML node type was Element, but the actual type is Text.

The following is the source of the sample application that I wrote:

using Microsoft.Exchange.WebServices.Data;
using System;
using System.Net;

namespace ExampleProgram
{
    class Program
    {
        public static StreamingSubscriptionConnection streamingConnection;

        public static bool RedirectionUrlValidationCallback(string redirectionUrl)
        {
            bool result = false;

            Uri redirectionUri = new Uri(redirectionUrl);

            if (redirectionUri.Scheme == "https")
            {
                result = true;
            }

            return result;
        }

        public static void NewMailSubscriptionDisconnect(object sender, SubscriptionErrorEventArgs args)
        {
            Exception e = args.Exception;
            Console.Write("Disconnect: ");
            Console.WriteLine(e.Message);

            if (streamingConnection != null && !streamingConnection.IsOpen)
            {
                streamingConnection.Open();
            }
        }

        public static void NewMailSubscriptionError(object sender, SubscriptionErrorEventArgs args)
        {
            Exception e = args.Exception;
            Console.Write("Disconnect: ");
            Console.WriteLine(e.Message);
        }

        public static void NewMailSubscriptionNotification(object sender, NotificationEventArgs args)
        {
            Console.WriteLine("New message has arrived");
        }

        static void Main(string[] args)
        {
            var exchangeService = new ExchangeService(ExchangeVersion.Exchange2013_SP1);

            exchangeService.Credentials = new NetworkCredential("username", "password", "domain");
            exchangeService.TraceEnabled = true;
            exchangeService.TraceFlags = TraceFlags.All;
            exchangeService.TraceEnablePrettyPrinting = true;
            exchangeService.AutodiscoverUrl("username@example.com", RedirectionUrlValidationCallback);

            var newMailSubscription = exchangeService.SubscribeToStreamingNotificationsOnAllFolders(EventType.NewMail);

            streamingConnection = new StreamingSubscriptionConnection(exchangeService, 30);
            streamingConnection.AddSubscription(newMailSubscription);
            streamingConnection.OnNotificationEvent += new StreamingSubscriptionConnection.NotificationEventDelegate(NewMailSubscriptionNotification);
            streamingConnection.OnSubscriptionError += new StreamingSubscriptionConnection.SubscriptionErrorDelegate(NewMailSubscriptionError);
            streamingConnection.OnDisconnect += new StreamingSubscriptionConnection.SubscriptionErrorDelegate(NewMailSubscriptionDisconnect);
            streamingConnection.Open();

            do { } while (Console.ReadKey(true).Key != ConsoleKey.Escape);
        }
    }
}

As you can see from the above source, I have tracing turned on. The following is what is yielded from those traces:

EwsResponseHttpHeader

<Trace Tag="EwsResponseHttpHeaders" Tid="17" Time="2015-10-20 17:42:31Z">
    HTTP/1.1 200 OK
    Transfer-Encoding: chunked
    request-id: <redacted>
    X-CalculatedBETarget: EXAMPLE-EXCHANGE-01.example.com
    X-NoBuffering: 1
    X-DiagInfo: EXAMPLE-EXCHANGE-01
    X-BEServer: EXAMPLE-EXCHANGE-01
    Cache-Control: private
    Set-Cookie: exchangecookie=<redacted>; path=/,X-BackEndCookie=<redacted>; expires=Thu, 19-Nov-2015 17:42:30 GMT; path=/ews; secure; HttpOnly
    Server: Microsoft-IIS/8.5
    X-AspNet-Version: 4.0.30319
    Persistent-Auth: true
    X-Powered-By: ASP.NET
    X-FEServer: EXAMPLE-EXCHANGE-02
    Date: Tue, 20 Oct 2015 17:42:30 GMT
</Trace>

EwsResponse

<Trace Tag="EwsResponse" 
       Tid="15" 
       Time="2015-10-20 16:52:07Z" 
       Version="0.0.0.0">

    417    <!-- What is this? -->

    <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">

        <soap11:Header xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
            <ServerVersionInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                               MajorVersion="15" 
                               MinorVersion="0" 
                               MajorBuildNumber="1130" 
                               MinorBuildNumber="6" 
                               Version="V2_23" 
                               xmlns="http://schemas.microsoft.com/exchange/services/2006/types" />
        </soap11:Header>

        <soap11:Body xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
            <m:GetStreamingEventsResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                                          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                                          xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" 
                                          xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
                <m:ResponseMessages>
                    <m:GetStreamingEventsResponseMessage ResponseClass="Success">
                        <m:ResponseCode>NoError</m:ResponseCode>
                        <m:ConnectionStatus>OK</m:ConnectionStatus>
                    </m:GetStreamingEventsResponseMessage>
                </m:ResponseMessages>
            </m:GetStreamingEventsResponse>

        </soap11:Body>

    </Envelope>

    2    <!-- Not sure what this is either... -->

</Trace>

Exception Detail

Microsoft.Exchange.WebServices.Data.ServiceXmlDeserializationException occurred
  HResult=-2146233088
  Message=The expected XML node type was Element, but the actual type is Text.
  Source=Microsoft.Exchange.WebServices
  StackTrace:
       at Microsoft.Exchange.WebServices.Data.EwsXmlReader.Read(XmlNodeType nodeType) in C:\Projects\ews-managed-api\Core\EwsXmlReader.cs:line 187
  InnerException: 

The source of EwsXmlReader.cs can be found at: https://github.com/OfficeDev/ews-managed-api/blob/master/Core/EwsXmlReader.cs

It looks like "something" is prepending 417 and appending 2 to the response from the Exchange server. It's quite obvious to me why the exception is being thrown, there is text data where there shouldn't be. What's not obvious to me, is why that text data is there.

Any ideas?


Solution

  • Transfer-Encoding: chunked
    

    That's the key to this puzzle, you are seeing the "chunks". 417 is a value in hexadecimal for the length of the <Envelope> chunk when you remove the pretty-print formatting. 2 is the final chunk, just whitespace. Chunked transfer formatting is explained here.

    I reformatted the XML to remove the white space, You can count off exactly 0x417 = 1047 characters:

    <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><soap11:Header xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/"><ServerVersionInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" MajorVersion="15" MinorVersion="0" MajorBuildNumber="1130" MinorBuildNumber="6" Version="V2_23" xmlns="http://schemas.microsoft.com/exchange/services/2006/types"/></soap11:Header><soap11:Body xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/"><m:GetStreamingEventsResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"><m:ResponseMessages><m:GetStreamingEventsResponseMessage ResponseClass="Success"><m:ResponseCode>NoError</m:ResponseCode><m:ConnectionStatus>OK</m:ConnectionStatus></m:GetStreamingEventsResponseMessage></m:ResponseMessages></m:GetStreamingEventsResponse></soap11:Body></Envelope>
    

    Obviously the http transfer is supposed to remove them, your question gives no decent lead why this did not happen. But hopefully a pretty good lead to find the underlying cause. Fun puzzle btw :)