Laden...

Microsoft Exchange 2010 EWS API 2.0 | Kontaktordner sync

Erstellt von osiris13371 vor 7 Jahren Letzter Beitrag vor 7 Jahren 1.720 Views
O
osiris13371 Themenstarter:in
1 Beiträge seit 2016
vor 7 Jahren
Microsoft Exchange 2010 EWS API 2.0 | Kontaktordner sync

Hallo zusammen,

ich bin neu hier und stelle mich einmal kurz vor. Mein Name ist Kai Wendt, 29 Jahre alt. Ich bin neben mein Job als System Engineer noch Hobby-Programmierer (vorallem C#).

Ich komme aktuell einfach nicht weiter....

Meine Aufgabe:
Ziel ist es ein Tool zu entwickeln das Kontakte / Kontakte Ordner von einem Postfach in diverse andere Postfächer kopiert / syncronisiert. Also es gibt ein Quellpostfach das nur von bestimmten Personen angepasst wird, bzw. neue Kontakte hinzugefügt / gelöscht werden. Diese sollen dann automatisch in die Zielpostfächer syncronisiert werden.

Ich habe mich für einen Windows-Dienst entschieden. Beim Start werden Initial alle Ordner / Kontakte in die Zielpostfächer kopiert. Der Dienst wird jede Nacht einmal neugestartet um einen neuen Initial Sync auszuführen.

Wenn jetzt ein einzelner Kontakt dazu kommt wird dieser sofort in die Zielpostfächer kopiert. (Das ist erstmal kein Problem)

Probleme habe ich bei gelöschten Kontakten und modifizierten Kontakten, diese sollten am besten auch sofort in den Zielpostfächern gelöscht oder geupdatet werden. Als eindeutiges Merkmal für die Items habe ich die itemID verwendet. Diese merke ich mir und finde sie im Zielpostfach wieder und möchte es gerne löschen oder updaten...

Beim Löschen tritt das phänomen auf das er immer den letzten angelegten Kontakt löscht und nicht den ich wirklich im Quellpostfach gelöscht habe. Wenn ich mir die ItemID vor dem Löschen ausgeben lasse dann ist diese auch korrekt! Aber dennoch wird immer der letzte Kontakt gelöscht.

Hat vielleicht jemand von euch noch eine Idee oder vielleicht soetwas schonmal gemacht?

Ich zeige euch erstmal meinen Quellcode von den einzelnen Events die auftreten könnten.

Ich stelle auch gerne das gesamte Projekt zur Verfügung wenn mir jemand helfen kann.

Vielen Dank.

Gruß,
Kai


// Events
        private void OnNotificationEvent(object sender, NotificationEventArgs args)
        {
    
            foreach (var notification in args.Events)
            {
                aLogger.writeLog("EWSFolderWatcher.OnNotificationEvent for Event Type: " + notification.EventType.ToString() + " Item Type: " + notification.GetType());

                    switch (notification.GetType().ToString())
                    {
                        case "Microsoft.Exchange.WebServices.Data.ItemEvent":
                            {
                                // wenn das event created ist, kopiere es in den Zielordner, und setze dabei die GUID Property.
                                
                                ItemEvent itemEvent = (ItemEvent)notification;
                          
                                aLogger.writeLog("ID : " + itemEvent.ItemId + "old ID : " + itemEvent.OldItemId + "Timestamp: " + itemEvent.TimeStamp.ToString());
                                Contact aContact = (Contact)Item.Bind(service, itemEvent.ItemId);
                                //Contact oldItem = (Contact)Item.Bind(service, itemEvent.OldItemId);   
                 
                                aLogger.writeLog("The Contact:  " + aContact.DisplayName);
                                aLogger.writeLog("located in " + Folder.Bind(service, aContact.ParentFolderId).DisplayName);
                                aLogger.writeLog("has been affected.");
                            
                                List<EmailAddress> targetMailboxes = EWSFolderWatcher.getDLMembers(aSourceFolderSyncGroup.sourcesyncgroupname, service);

                                foreach (EmailAddress aTarget in targetMailboxes)
                                {
                                    aLogger.writeLog("checking " + aTarget.Address.ToString().ToLower());
                                    //
                                    // ensure user folders exist
                                    //
                                    FolderView aView = new FolderView(int.MaxValue);
                                    aView.Traversal = FolderTraversal.Shallow; // only check for sub-folder level
                                    SearchFilter searchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, myFolder.DisplayName);
                                    FindFoldersResults mFolderResults;

                                    try
                                    {
                                        FolderId mContactsFolderId = new FolderId(WellKnownFolderName.Contacts, new Mailbox(aTarget.Address));
                                        Folder mContactsFolder = Folder.Bind(service, mContactsFolderId);
                                        mFolderResults = mContactsFolder.FindFolders(searchFilter, aView);
                                        Folder destinationFolder = mFolderResults.Folders[0];

                                        aLogger.writeLog(notification.EventType.ToString().ToUpper());

                                    switch (notification.EventType.ToString().ToUpper())                                    
                                        {
                                            case "CREATED":
                                                {

                                                
                                                FindItemsResults<Item> targetItemsList = mainTargetFolder.FindItems(new ItemView(int.MaxValue));
                                                //oldItemDictionary.Clear();

                                               aContact.Copy(destinationFolder.Id);
                                                
                                                if (connectorList.Count < 1)
                                                {
                                                    foreach (Item item in targetItemsList)
                                                    {
                                                        connectorList.Add(new connector { DaddyIdAsString = aContact.Id.ToString(), id = 0, ChildBirthDate = item.DateTimeCreated, ChildIdAsString = item.Id.ToString(), Name = aContact.DisplayName.ToString() });
                                                    }
                                                }
                                                else
                                                {
                                                    foreach (var item in targetItemsList)
                                                    {
                                                        if (!connectorList.Any(x => string.Compare(x.ChildBirthDate.ToString(), item.DateTimeCreated.ToString(), false) == 0))
                                                        {
                                                            int zahl = connectorList.Max(x => x.id);
                                                            zahl++;
                                                            aLogger.writeLog("Meine Neue ID" + zahl);
                                                            connectorList.Add(new connector { DaddyIdAsString = aContact.Id.ToString(), id = zahl, ChildBirthDate = item.DateTimeCreated, ChildIdAsString = item.Id.ToString(), Name = aContact.DisplayName.ToString() });
                                                        }
                                                    }
                                                }


                                                foreach (var item in connectorList)
                                                {
                                                    aLogger.writeLog("Connector initID: " + item.id + " DaddyID: " + item.DaddyIdAsString + " ChildBirthDate:" + item.ChildBirthDate + " ChildId: " + item.ChildIdAsString + " DisplayName:" + item.Name);
                                                }

                                                
                                                break;
                                                

                                                }

                                            case "MOVED": // delete action
                                                {

                                                

                                                FindItemsResults<Item> targetItemsList = mainTargetFolder.FindItems(new ItemView(int.MaxValue));

                                                foreach (var item in targetItemsList)
                                                {
                                                    if (!connectorList.Any(x => string.Compare(x.ChildBirthDate.ToString(), item.DateTimeCreated.ToString(), false) == 0))
                                                    {
                                                        int zahl = connectorList.Max(x => x.id);
                                                        zahl++;
                                                        aLogger.writeLog("Meine Neue ID" + zahl);
                                                        connectorList.Add(new connector { DaddyIdAsString = aContact.Id.ToString(), id = zahl, ChildBirthDate = item.DateTimeCreated, ChildIdAsString = item.Id.ToString(), Name = aContact.DisplayName.ToString() });
                                                    }
                                                }

                                                aLogger.writeLog("Move Item oldID: " + itemEvent.OldItemId + " ItemID: " + itemEvent.ItemId + " Name: " + aContact.DisplayName);

                                                foreach (var item in connectorList)
                                                {
                                                    aLogger.writeLog("MOVE Connector initID: " + item.id + " DaddyID: " + item.DaddyIdAsString + " ChildBirthDate:" + item.ChildBirthDate + " ChildId: " + item.ChildIdAsString + " DisplayName:" + item.Name);
                                                }


                                                
                                                connector childElement = connectorList.First(x => string.Compare(x.DaddyIdAsString, itemEvent.ItemId.ToString(), false) == 0);

                                                aLogger.writeLog("Zu Löschen: " + childElement.Name + " childID: " + childElement.ChildIdAsString + " DaddyID: " + childElement.DaddyIdAsString);

                                                aLogger.writeLog("Looking For: " + childElement.ChildIdAsString);

                                                

                                                Item elementToDelete = targetItemsList.First(x => string.Compare(x.DateTimeCreated.ToString(), childElement.ChildBirthDate.ToString(),false) == 0 && string.Compare(x.Id.ToString(), childElement.ChildIdAsString,false )== 0);
                                                aLogger.writeLog("DELETING ID: " + elementToDelete.Id);


                                                Contact elementToDelete1 = (Contact)Item.Bind(service, elementToDelete.Id);

                                                //elementToDelete.Move(WellKnownFolderName.DeletedItems);

                                                elementToDelete1.Delete(DeleteMode.HardDelete);

                                                connectorList.Remove(childElement);
                                                
                                                aLogger.writeLog("Item moved/deleted Event: done");

                                                break;
                                                }

                                            case "MODIFIED":
                                                {

                                                FindItemsResults<Item> targetItemsList = mainTargetFolder.FindItems(new ItemView(int.MaxValue));

                                                foreach (var item in targetItemsList)
                                                {
                                                    if (!connectorList.Any(x => string.Compare(x.ChildBirthDate.ToString(), item.DateTimeCreated.ToString(), false) == 0))
                                                    {
                                                        int zahl = connectorList.Max(x => x.id);
                                                        zahl++;
                                                        aLogger.writeLog("Meine Neue ID" + zahl);
                                                        connectorList.Add(new connector { DaddyIdAsString = aContact.Id.ToString(), id = zahl, ChildBirthDate = item.DateTimeCreated, ChildIdAsString = item.Id.ToString(), Name = aContact.DisplayName.ToString() });
                                                    }
                                                }

                                                aLogger.writeLog("Update Item oldID: " + itemEvent.OldItemId + " ItemID: " + itemEvent.ItemId + " Name: " + aContact.DisplayName);

                                                foreach (var item in connectorList)
                                                {
                                                    aLogger.writeLog("UPDATE Connector initID: " + item.id + " DaddyID: " + item.DaddyIdAsString + " ChildBirthDate:" + item.ChildBirthDate + " ChildId: " + item.ChildIdAsString + " DisplayName:" + item.Name);
                                                }



                                                connector childElement = connectorList.First(x => string.Compare(x.DaddyIdAsString, itemEvent.ItemId.ToString(), false) == 0);

                                                aLogger.writeLog("Zu Updaten: " + childElement.Name + " childID: " + childElement.ChildIdAsString + " DaddyID: " + childElement.DaddyIdAsString);

                                                aLogger.writeLog("Looking For: " + childElement.ChildIdAsString);

                                                Item elementToUpdate = targetItemsList.First(x => string.Compare(x.DateTimeCreated.ToString(), childElement.ChildBirthDate.ToString(), false) == 0 && string.Compare(x.Id.ToString(), childElement.ChildIdAsString, false) == 0);
                                                aLogger.writeLog("Update ID: " + elementToUpdate.Id);

                                                elementToUpdate.Update(ConflictResolutionMode.AlwaysOverwrite);
                                                
                                                connectorList.Add(childElement);

                                                aLogger.writeLog("Item updating Event: done");



                                                // just create copy to target folder    
                                                //Item aNewTargetItem = aContact.Copy(destinationFolder.Id);
                                                //targetSourceIdMappings.Add(aNewTargetItem, aContact);
                                                //aLogger.writeLog("modified item " + aContact.Id + " copied/mapped to " + aNewTargetItem.Id);
                                                //aLogger.writeLog("finished: Looking for items to refresh.");

                                                break;
                                                }


                                            case "DELETED":
                                                {

                                                    break;
                                                }

                                        default:
                                                {
                                                    aLogger.writeLog("no action defined for " + notification.EventType.ToString().ToUpper() + " as an ItemEvent");
                                                    break;
                                                }
                                        }
                                    }

                                    catch (Exception taor)
                                    {
                                        aLogger.writeLog("Exception: " + taor.Message + " InnerException " + taor.InnerException);
                                    }
                                }

                                break;

T
708 Beiträge seit 2008
vor 7 Jahren

Hallo Kai,

ich finde die Methode doch sehr unübersichtlich...
Die kann man sicherlich noch etwas schöner machen und in mehrere Funktionen aufteilen.
Das wird u.a. auch eine mögliche Fehlerquelle sein.

Beim überfliegen des Codes ist mir aufgefallen, dass Du beim Erstellen des neuen Kontaktes die "DaddyId" und die eigene ID setzt.

connectorList.Add(new connector { DaddyIdAsString = aContact.Id.ToString(), id = zahl, ChildBirthDate = item.DateTimeCreated, ChildIdAsString = item.Id.ToString(), Name = aContact.DisplayName.ToString() });

Dazu holst Du Dir überflüssiger Weise wieder alle Elemente des Ordners und vergleichst das "ChildBirthDate" bis Du den vermeintlich neuen Kontakt gefunden hast.

Beide Methoden Move() und Copy() haben als Rückgabewert ein OutlookItem. Das solltest Du auch verwenden!

Damit kannst Du auf die Schleife und den Vergleich verzichten. Denke da liegt auch das Problem beim füllen Deiner Liste. Denn imho ist diese verkehrt und gar nicht unbedingt das Löschen an sich.

1.029 Beiträge seit 2010
vor 7 Jahren

Hi,

noch als Tipp - das was du dort mühsam baust gibt es schon.

Wir setzen da "CodeTwo Exchange Sync" ein und sind bisher sehr glücklich damit. (> 2 Jahre im Einsatz)

Nur falls du mal drüber rechnen möchtest: warn damals ~600 €.

LG

Edit:
Hatte damals nämlich selbst mit mir gehadert, ob ich das selbst machen möchte - mich jedoch mangels entsprechender Testsysteme bzw. dem damit verbundenen Aufwand dazu entschiedenen lieber eine fertig getestete Komponenten zu holen, bei der ich nicht selber schuld bin, falls auf Grund irgendeines Fehlers einfach Informationen fehlen oder falsch sind...