Search code examples
.netexchangewebservicesexchange-server-2010ews-managed-api

.NET Handling Event Notifications in Exchange Server EWS Managed API


When dealing with NotificationEvents in EWS the following MSDN docs https://msdn.microsoft.com/en-us/library/office/hh312849(v=exchg.140).aspx written by Henning Krause.

Shows 2 different approaches to tackling the subject, see the code below:

EX 1

private static void OnNotificationEvent(object sender, NotificationEventArgs args)
    {
        // Extract the item ids for all NewMail Events in the list.
        var newMails = from e in args.Events.OfType<ItemEvent>()
                       where e.EventType == EventType.NewMail
                       select e.ItemId;

        // Note: For the sake of simplicity, error handling is ommited here. 
        // Just assume everything went fine
        var response = _ExchangeService.BindToItems(newMails,
                                                    new PropertySet(BasePropertySet.IdOnly, ItemSchema.DateTimeReceived,
                                                                    ItemSchema.Subject));
        var items = response.Select(itemResponse => itemResponse.Item);

        foreach (var item in items)
        {
            Console.Out.WriteLine("A new mail has been created. Received on {0}", item.DateTimeReceived);
            Console.Out.WriteLine("Subject: {0}", item.Subject);
        }
    }

    private static void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args)
    {
        // Handle error conditions. 
        var e = args.Exception;
        Console.Out.WriteLine("The following error occured:");
        Console.Out.WriteLine(e.ToString());
        Console.Out.WriteLine();
    }


}

EX 2

private static void OnNotificationEvent(object sender, NotificationEventArgs args){
   foreach (var notification in args.Events){
      if (notification.EventType != EventType.NewMail) continue;
      Console.WriteLine("A new mail has been created");
      var itemEvent = (ItemEvent) notification;
      Console.WriteLine("The item ID of the new mail is {0}", itemEvent.ItemId.UniqueId);
   }
}

What are the differences/advantages of using one approach over the other?

The example only shows how to handle 1 particular EventType but in my app I'm actually wanting to know when and items gets 1. Updated and 2. Deleted.

See below:

Private Sub OnEvent(sender As System.Object, args As NotificationEventArgs)
    Dim oGuid As New Guid(DefaultExtendedPropertySet.PublicStrings)
    Dim oInternalContactId As New ExtendedPropertyDefinition(oGuid, conContactIdPropertyName, MapiPropertyType.Integer)
    Dim oDateAdded As New ExtendedPropertyDefinition(oGuid, conDteAddedPropertyName, MapiPropertyType.String)
    Dim oDateUpdated As New ExtendedPropertyDefinition(oGuid, conDteUpdatedPropertyName, MapiPropertyType.String)
    Dim lstUpdatedContactIds As New List(Of ItemId)
    Dim lstDeletedContactIds As New List(Of ItemId)
    Dim lstUpdatedContacts As New List(Of Contact)
    Dim lstDeletedContacts As New List(Of Contact)
    Dim oUpdatedContacts As ServiceResponseCollection(Of GetItemResponse)
    Dim oDeletedontacts As ServiceResponseCollection(Of GetItemResponse)
    Dim intInternalContactId As Integer

    lstUpdatedContactIds = From e In args.Events.OfType(Of ItemEvent)()
                           Where e.EventType = EventType.Modified
                           Select e.ItemId

    lstDeletedContactIds = From e In args.Events.OfType(Of ItemEvent)()
                           Where e.EventType = EventType.Deleted
                           Select e.EventType


    If lstUpdatedContactIds.Count > 0 Then
        oUpdatedContacts = args.Subscription.Service.BindToItems(lstUpdatedContactIds, New PropertySet(BasePropertySet.FirstClassProperties, oInternalContactId, oDateAdded, oDateUpdated))
        lstUpdatedContacts = oUpdatedContacts.Where(Function(collection) collection.Item.TryGetProperty(oInternalContactId, intInternalContactId))
    End If

    If lstDeletedContactIds.Count > 0 Then
        oDeletedontacts = args.Subscription.Service.BindToItems(lstDeletedContactIds, New PropertySet(BasePropertySet.FirstClassProperties, oInternalContactId, oDateAdded, oDateUpdated))
        lstDeletedContacts = oDeletedontacts.Where(Function(collection) collection.Item.TryGetProperty(oInternalContactId, intInternalContactId))
    End If

    Next
End Sub 

Am I in the right track following the approach in EX 1 or am I better off following EX 2?

If the OnNotificationEvent fires every time an Event is caught, why are we expecting a Collection of Events (EX 1) and using LINQ, shouldn't we be expecting a single event?

How does Exchange handle multiple contiguous Event Notifications form different MailBoxes does it automatically Queues them until we process them?

Keep in mind that I'm monitoring hundreds of MailBoxes at the same time.

Thanks!


Solution

  • As you will find out, what seems like a discreet action in Exchange, e.g. a new item is created, can often result in many notifications being delivered to your event handler. Now I've exclusively dealt with calendar items, and the workflow there for auto-accept causes multiple events all the time. With standard email items in the Inbox, I'm not sure what's going to happen, but it's possible there might be changes coming in along with NewMail events. In my experience, multiple notifications in each event handler call are always for a single mailbox.

    I don't quite get the difference between EX1 and EX2, but I would encourage you NOT to BindToItems in the event handler. It is better to save off the ItemIds and notification type and to process them on another mainline thread. As with any event handler, you want to minimize the time you're in there.

    HTH