订阅交换流通知时出现异常

Exception when subscribing to exchange streaming notifications

我目前正在从事一个让我与 Exchange 集成的项目。其中一项要求是监视邮箱中是否有新的传入消息,我认为利用 streaming 通知是个好主意。

我编写了一个示例应用程序来熟悉如何利用流式通知,但是我遇到了以下错误:The expected XML node type was Element, but the actual type is Text.

以下是我写的示例应用程序的来源:

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);
        }
    }
}

正如您从上面的源代码中看到的那样,我打开了跟踪功能。以下是从这些痕迹中产生的结果:

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>

异常详细信息

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: 

EwsXmlReader.cs 的来源可在以下位置找到:https://github.com/OfficeDev/ews-managed-api/blob/master/Core/EwsXmlReader.cs

看起来 "something" 是在 417 前面加上 2 到来自 Exchange 服务器的响应。对我来说,为什么抛出异常是很明显的,在不应该存在的地方有文本数据。对我来说不明显的是为什么文本数据在那里。

有什么想法吗?

Transfer-Encoding: chunked

这就是这个谜题的关键,您看到的是 "chunks"。 417 是删除漂亮打印格式时 <Envelope> 块长度的十六进制值。 2 是最后一个块,就是 whitespace。分块传输格式为 explained here.

我重新格式化了 XML 以删除白色 space,你可以算出 0x417 = 1047 个字符:

<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>

显然 HTTP 传输应该删除它们,您的问题没有给出为什么没有发生这种情况的正确线索。但希望有一个很好的线索来找到根本原因。有趣的拼图顺便说一句:)