Day of the Developer

Living the life of a developer. What is development work really like?

<April 2008>
SuMoTuWeThFrSa
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

Post Categories

Article Categories

News

I'm a dad :) Welcome to a new life.

Navigation

Software Business Tips

My Sites

Subscriptions



Fun with Exchange 2007 Push Notifications

Now, you would think this should be pretty straight forward by now. But it's not.

Scenario: I am subscribed to a users calendar as follows:

BaseFolderIdType[] folders = new BaseFolderIdType[1];
DistinguishedFolderIdType folderId = new DistinguishedFolderIdType();
folderId.Id = DistinguishedFolderIdNameType.calendar;
folders[0] = folderId;
pushSubscription.FolderIds = folders;


// Subscribe to all events.
NotificationEventTypeType[] eventTypes = new NotificationEventTypeType[5];
eventTypes[0] = NotificationEventTypeType.CopiedEvent;
eventTypes[1] = NotificationEventTypeType.CreatedEvent;
eventTypes[2] = NotificationEventTypeType.DeletedEvent;
eventTypes[3] = NotificationEventTypeType.ModifiedEvent;
eventTypes[4] = NotificationEventTypeType.MovedEvent; pushSubscription.EventTypes = eventTypes;

In the notification function, I check as follows for each item I am notified of as per PushNotificationClient.cs in the SDK:

int i = 0;
// Cast the notification event to the proper type
foreach (BaseNotificationEventType bnet in notification.Items)
{
    // Get the event name
    string eventName = notification.ItemsElementName[i].ToString();
    BaseObjectChangedEventType it = bnet as BaseObjectChangedEventType;
    if (it == null)
    {
        continue;
    }
    if (!(it.Item is ItemIdType))
    {
        continue;
    }
// Code to display details about the event
ItemIdType item = it.Item as ItemIdType;
Debug.WriteLine(eventName.PadRight(20) + "[" + (bnet.GetType().ToString() + "]:").PadLeft(35, ' ') + item.Id + "\t\t" + item.ChangeKey);

Now, you would think that when you create an appointment, you would get a CreatedEvent, when you do a permanent delete you would get a DeletedEvent, and so on. But this is what you really get:

===== OWA =====
CREATE
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5RAAriVlgoAAAAAAAAA==
IPM.Appointment: fghfhdfghdfghdfgh
EXPANDED / CONTRACT / MOVE WITHIN CALENDAR
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5RAAriVlgpQAAAAAAAA==
No Messages Matched: ErrorItemNotFound
CreatedEvent[ModifiedEventType]RAAQUKzDsAAA5RAAriVlgoQAADwAAAA==
IPM.Appointment: fghfhdfghdfghdfgh
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5RAAriVlgpQAAAAAAAA==
No Messages Matched: ErrorItemNotFound
SOFT DELETE
ModifiedEvent[MovedCopiedEventType]RAAQUK0ABgAA5RAAriVlwzQAAAAAAAA==
IPM.Appointment: fghfhdfghdfghdfgh
=== OUTLOOK ===
CREATE
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEAwAADwAAAA==
IPM.Appointment: TEST 5
EXPANDED / CONTRACT / MOVE WITHIN CALENDAR
ModifiedEvent[ModifiedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEAwAADwAAAA==
IPM.Appointment: TEST 5
MOVED FOLDER / SOFT DELETE / SOFT DELETE RESTORE
ModifiedEvent[MovedCopiedEventType]eAAriVgADAAA5jp9kS9UdUCKFiIaz2NQeAAriVgSAQAAAAAAAA==
IPM.Appointment: TEST 5
COPIED WITHIN CALENDAR
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEBAAADwAAAA==
IPM.Appointment: TEST 5
HARD DELETE
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEBAAADwAAAA==
No Messages Matched: ErrorItemNotFound

Not exactly sensible. but I think I've found the problem.

for (int i = 0;i < notification.Items.Length; i++)
{
    BaseNotificationEventType bnet = notification.Items[i];
    // Get the event name
    string eventName = notification.ItemsElementName[i].ToString();
    BaseObjectChangedEventType it = bnet as BaseObjectChangedEventType;
    if (it == null)
    {
        continue;
    }
    if (!(it.Item is ItemIdType))
    {
        continue;
    }
    // Code to display details about the event
    ItemIdType item = it.Item as ItemIdType;
    Debug.WriteLine(eventName.PadRight(20) + "[" + (bnet.GetType().ToString() + "]:").PadLeft(35, ' ') + item.Id + "\t\t" + item.ChangeKey);

If you replace the foreach with a for loop instead, so you can make sure the item and the event name line up, you get:

===== OWA =====
CREATE
CreatedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2JgAAAAAAAA==
No Messages Matched: ErrorItemNotFound
CreatedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2JwAADwAAAA==
IPM.Appointment: TEST 6
DeletedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2JgAAAAAAAA==
No Messages Matched: ErrorItemNotFound
EXPANDED / CONTRACT / MOVE WITHIN CALENDAR
CreatedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2KAAAAAAAAA==
No Messages Matched: ErrorItemNotFound
ModifiedEvent[ModifiedEventType]GRlvYJ3GL/RAArjVW2JwAADwAAAA==
IPM.Appointment: TEST 6
DeletedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2KAAAAAAAAA==
No Messages Matched: ErrorItemNotFound
SOFT DELETE
MovedEvent[MovedCopiedEventType]GRlvYJ3GL/RAArjVXWTQAAAAAAAA==
IPM.Appointment: TEST 6
SOFT DELETE RESTORE
CreatedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2KwAAAAAAAA==
IPM.SchedulePlus.FreeBusy.BinaryData:
MovedEvent [MovedCopiedEventType]:GRlvYJ3GL/RAArjVW2LAAAAAAAAA==
IPM.Appointment: TEST 6
DeletedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2KwAAAAAAAA==
No Messages Matched: ErrorItemNotFound
=== OUTLOOK ===
CREATE
CreatedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECQAADwAAAA==
IPM.Appointment: TEST 5
EXPANDED / CONTRACT / MOVE WITHIN CALENDAR
ModifiedEvent[ModifiedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECQAADwAAAA==
IPM.Appointment: TEST 5
MOVED FOLDER / SOFT DELETE / SOFT DELETE RESTORE
MovedEvent[MovedCopiedEventType]RAAQUK0ABgAA5jp9kS9UdUCKFiIaz2NQeAAriVgUBAAADwAAAA==
IPM.Appointment: TEST 5
COPIED WITHIN CALENDAR
CreatedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECgAADwAAAA==
IPM.Appointment: TEST 5
HARD DELETE
DeletedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECgAADwAAAA==
No Messages Matched: ErrorItemNotFound

It looks like OWA is still quite different from Outlook, but now at least the event types and event names go together much more sensibly.

posted on Wednesday, April 02, 2008 10:49 AM by admin

# re: Fun with Exchange 2007 Push Notifications @ Tuesday, April 01, 2008 6:05 PM

And as an aside, can someone please tell me why BaseObjectChangedEventType doesn't include an ObjectType property so you wouldn't have to call GetItem just to find that out. Particularly since it fails on deleted objects.

Roger Willcocks

Powered by Community Server, by Telligent Systems