2015-04-15 2 views
3

У меня есть приложение, которое уведомляет о новой почте, созданной с помощью управляемой EWS api (v2.2). Я использую StreamingSubscription для прослушивания событий почтового ящика. Я заметил, что иногда событие NewMail не запускается (я вижу необработанную почту в почтовом ящике позже), исключение подключения/подписки не возникает, и через некоторое время новая почта получает, поскольку ничего не произошло ... что может вызвать такое поведение? В биржевых журналах нет ничего подозрительного, событие просто не уволено ... Любые идеи и предложения будут оценены.Обмен EWS иногда не срабатывает Событие NewMail с использованием StreamingSubscription

Спасибо.

Источник:

public class ExchangeClient : IDisposable 
{ 
    private ExchangeService _exchange; 
    private SubscriptionBase _subscription; 
    private StreamingSubscriptionConnection _connection; 

    private bool _disposed; 
    private bool _disposing; 

    public event EventHandler<ExchangeEventArgs> ExchangeEvent; 

    public ExchangeClient(string userName, string password, string domain, ExchangeVersion version) 
    { 
     _exchange = new ExchangeService(version); 
     _exchange.Credentials = new WebCredentials(userName, password); 

     _exchange.AutodiscoverUrl(userName + "@" + domain); 

     var ids = new FolderId[2] { new FolderId(WellKnownFolderName.Root), new FolderId(WellKnownFolderName.Inbox) }; 
     var events = new List<EventType>(); 
     events.Add(EventType.NewMail); 

     _subscription = _exchange.SubscribeToStreamingNotifications(ids, events.ToArray()); 
     _connection = new StreamingSubscriptionConnection(_exchange, 30); 
     _connection.AddSubscription((StreamingSubscription)_subscription); 
     _connection.OnNotificationEvent += OnNotificationEvent; 
     _connection.OnSubscriptionError += OnSubscriptionError; 
     _connection.OnDisconnect += OnDisconnect; 
     _connection.Open(); 
    } 

    private void OnDisconnect(object sender, SubscriptionErrorEventArgs args) 
    { 
     if (!_disposing && _connection != null) 
     { 
      _connection.Open(); 
     } 
    } 

    private void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args) 
    { 
     throw args.Exception; 
    } 

    private void OnNotificationEvent(object sender, NotificationEventArgs args) 
    { 
     if (_subscription != null) 
     { 
      if (args.Subscription.Id == _subscription.Id) 
      { 
       foreach (var notificationEvent in args.Events) 
       { 
        switch (notificationEvent.EventType) 
        { 
         case EventType.Status: 
          break; 

         case EventType.NewMail: 
          NotificationReceived(new ExchangeEventArgs(
          notificationEvent.EventType, 
          ((ItemEvent)notificationEvent).ItemId, ((ItemEvent)notificationEvent).ParentFolderId)); 
          break; 

         default: 
          break; 
        } 
       } 
      } 
     } 
    } 

    public void Disconnect() 
    { 
     if (_connection.IsOpen) 
      _connection.Close(); 
    } 

    private void NotificationReceived(ExchangeEventArgs e) 
    { 
     if (ExchangeEvent != null) 
     { 
      ExchangeEvent(this, e); 
     } 
    } 

    public void Dispose() 
    { 
     _disposing = true; 
     Dispose(_disposing); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing && !_disposed) 
     { 
      if (_connection != null) 
      { 
       if (_connection.IsOpen) 
        _connection.Close(); 
       _connection = null; 
      } 
      _exchange = null; 
      _disposed = true; 
     } 
    } 
} 

ответ

4

Я думаю, что я могу ответить на этот вопрос сам - чтобы гарантировать непрерывную работу, которую необходимо продлить подписку. Но вот более странная часть: исключение не исключено (есть объект исключения в SubscriptionErrorEventArgs внутри события OnDisconnect: Невозможно получить события для этой подписки. Подписка должна быть воссоздана.), Просто перерыв, когда вы не получите уведомление о событиях подписки и через некоторое время вы продолжите получать уведомления о событиях со старой подпиской ...

Обновление. Решение, с которым я столкнулся: если SubscriptionErrorEventArgss внутри события OnDisconnect не содержит исключения - просто откройте закрытое соединение, в противном случае - поднимите событие DIsconnected и разрешите родительскому классу - мы должны попробовать повторно подключиться или нет (путем вызова Reconnect).

public class ExchangeEventArgs : EventArgs 
{ 
    public EventType Type { get; private set; } 
    public ItemId ItemId { get; private set; } 
    public FolderId FolderId { get; private set; } 

    public ExchangeEventArgs(EventType type, ItemId itemId, FolderId folderId) 
    { 
     Type = type; 
     ItemId = itemId; 
     FolderId = folderId; 
    } 
} 

public class ExchangeClient : IDisposable 
{ 
    private ExchangeService _exchange; 
    private SubscriptionBase _subscription; 
    private StreamingSubscriptionConnection _connection; 

    private bool _disposed; 
    private bool _disposing; 

    public event EventHandler<ExchangeEventArgs> ExchangeEvent; 
    public event EventHandler<DisconnectEventArgs> Disconnected; 

    public ExchangeClient(string userName, string password, string domain, ExchangeVersion version) 
    { 
     _exchange = new ExchangeService(version); 
     _exchange.Credentials = new WebCredentials(userName, password); 
     _exchange.AutodiscoverUrl(userName + "@" + domain); 
     _connection = new StreamingSubscriptionConnection(_exchange, 30); 

     CreateSubscription(); 

     _connection.OnNotificationEvent += OnNotificationEvent; 
     _connection.OnSubscriptionError += OnSubscriptionError; 
     _connection.OnDisconnect += OnDisconnect; 
     _connection.Open(); 
    } 

    private void CreateSubscription() 
    { 
     var ids = new FolderId[2] { new FolderId(WellKnownFolderName.Root), new FolderId(WellKnownFolderName.Inbox) }; 
     var events = new List<EventType>(); 
     events.Add(EventType.NewMail); 
     if (_subscription != null) 
     { 
      ((StreamingSubscription)_subscription).Unsubscribe(); 
      _connection.RemoveSubscription((StreamingSubscription)_subscription); 
     } 
     _subscription = _exchange.SubscribeToStreamingNotifications(ids, events.ToArray()); 
     _connection.AddSubscription((StreamingSubscription)_subscription); 
    } 

    private void OnDisconnect(object sender, SubscriptionErrorEventArgs args) 
    { 
     if (args.Exception == null) 
     { 
      if (!_disposing && _connection != null) 
      { 
       _connection.Open(); 
      } 
     } 
     else 
     { 
      if (Disconnected != null) 
       Disconnected(this, new DisconnectEventArgs("Exchange exception", args.Exception)); 
     } 
    } 

    public bool Reconnect() 
    { 
     try 
     { 
      if (!_disposing && _connection != null) 
      { 
       CreateSubscription(); 

       _connection.Open(); 

       return true; 
      } 
      else 
       return false; 
     } 
     catch (Exception) 
     { 
      return false; 
     } 
    } 

    private void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args) 
    { 
     OnDisconnect(sender, args); 
    } 

    private void OnNotificationEvent(object sender, NotificationEventArgs args) 
    { 
     if (_subscription != null) 
     { 
      if (args.Subscription.Id == _subscription.Id) 
      { 
       foreach (var notificationEvent in args.Events) 
       { 
        switch (notificationEvent.EventType) 
        { 
         case EventType.Status: 
          break; 

         case EventType.NewMail: 
          NotificationReceived(new ExchangeEventArgs(
          notificationEvent.EventType, 
          ((ItemEvent)notificationEvent).ItemId, ((ItemEvent)notificationEvent).ParentFolderId)); 
          break; 

         default: 
          break; 
        } 
       } 
      } 
     } 
    }  

    public void Disconnect() 
    { 
     if (_connection.IsOpen) 
      _connection.Close(); 
    } 

    private void NotificationReceived(ExchangeEventArgs e) 
    { 
     if (ExchangeEvent != null) 
     { 
      ExchangeEvent(this, e); 
     } 
    } 

    public void Dispose() 
    { 
     _disposing = true; 
     Dispose(_disposing); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing && !_disposed) 
     { 
      if (_connection != null) 
      { 
       if (_connection.IsOpen) 
        _connection.Close(); 
       _connection = null; 
      } 
      _exchange = null; 
      _disposed = true; 
     } 
    } 
} 
+0

Итак, как вы продлеваете подписку? Внутри обработчика OnDisconnect или с помощью отдельного таймера? Не могли бы вы опубликовать изменения, внесенные вами в код, чтобы заставить его работать? –

+0

Мне также интересно узнать, как вы продлеваете подписку. Разум, отправляющий код? –

+0

@MikeRibeiro Я опубликовал этот код некоторое время назад - как описано в обновлении к исходному ответу: ** Решение, в котором я закончил: если SubscriptionErrorEventArgss внутри события OnDisconnect не содержит исключения - просто откройте закрытое соединение, в противном случае - поднимите DIsconnected событие, и пусть родительский класс решает - мы должны попробовать повторно подключиться или нет (путем вызова Reconnect). ** –

Смежные вопросы