我有应用程序通知使用EWS托管api(v2.2)创建的新邮件。我正在使用StreamingSubscription来监听邮箱事件。我注意到有时NewMail事件没有被触发(我后面看到邮箱中未处理的邮件),没有引发连接/订阅异常,并且在一段时间后新邮件接收没有发生任何事情......什么可能导致这样的行为?在交换日志中没有任何可疑之处,事件只是没有被解雇......任何想法和建议都将不胜感激。
感谢。
来源:
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;
}
}
}
答案 0 :(得分:5)
我想我可以自己回答这个问题 - 保证您续订订阅所需的持续工作。但这里是一个奇怪的部分:没有抛出异常(OnDisconnect事件中的SubscriptionErrorEventArgs中有一个异常对象: 无法检索此订阅的事件。必须重新创建订阅。),只有在您不会收到有关订阅事件的通知时才会超时,并且在一段时间后您将继续接收旧订阅的事件通知...
<强> UPD。强> 最终的解决方案是:如果OnDisconnect事件中的SubscriptionErrorEventArgss不包含异常 - 只需打开关闭连接,否则 - 引发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;
}
}
}