EWS托管API SyncFolderItems如何更新和删除/跟踪项目

时间:2012-06-27 06:10:15

标签: c# exchange-server ews-managed-api

我正在构建一个应用程序,该应用程序需要存在于受信任的域中,监视该域中的Exchange服务器上的邮箱日历集合,并将约会同步到一个或多个其他服务器上的不同邮箱。与之同步的邮箱在内部映射表(sqlce)中定义,该表由此应用程序的用户维护。

我遇到的问题是我无法找到跟踪远程约会的方法,以便我可以在必要时更新或删除它。在远程服务器上创建约会后,他们有一个新的itemid,它与本地Exchange服务器上的sync folder items调用返回的itemid不对应。我无法通过开始时间/主题找到该项目,因为这些项目可能已被更改或删除。

我的同步方法如下 - 我是以完全错误的方式进行此操作还是有更好的方法来使用SyncFolderItems方法?

到目前为止,我提出的解决问题的最佳方法是将远程约会的ItemID保存到本地约会的属性中,但即便如此,我也不确定是否会有效,因为我不知道哪些属性删除后维护?请帮助!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Exchange.WebServices.Data;
using System.Net;

namespace ProExchangeSync2012
{
    class ExchangeWebServiceMethods
    {

    public string ProExchangeSyncCalendars(string LocalMailbox
                                                ,string RemoteMailbox
                                                ,string SyncState    
                                                ,ExchangeService RemoteService
                                                ,ExchangeService LocalService
                                                )
    {
        //if SyncState is empty string set to null
        if (SyncState.ToString().Length == 0)
        { SyncState = null; }

        ExchangeService LocalExchangeService = LocalService;
        ExchangeService RemoteExchangeService = RemoteService;
        RemoteExchangeService.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress,RemoteMailbox);


        //Folders and mailboxes to pass to the webservice in SyncItems call.
        Mailbox DonorMailBox = new Mailbox(LocalMailbox);
        Mailbox DestinationMailBox = new Mailbox(RemoteMailbox);
        FolderId DonorFolder = new FolderId(WellKnownFolderName.Calendar, DonorMailBox);
        FolderId DestinationFolder = new FolderId(WellKnownFolderName.Calendar, DestinationMailBox);

        //Create a ChangeCollection object and call syncfolderitems on local exchange service.
        ChangeCollection<ItemChange> ItemChanges
        = LocalExchangeService.SyncFolderItems(new FolderId(WellKnownFolderName.Calendar, DonorMailBox) //PASS IN THE MAILBOX HERE>
                                        , PropertySet.FirstClassProperties
                                        , null
                                        , 512
                                        , SyncFolderItemsScope.NormalItems
                                        , SyncState
                                        );


        //Store the SyncState
        SyncState = ItemChanges.SyncState;

        //Fetch all the required properties of the items
        //LocalService.LoadPropertiesForItems(ItemChanges, PropertySet.FirstClassProperties);

        if (ItemChanges.Count == 0)
        {
            Console.WriteLine("There are no items to synchronize.");
        }
        else
        {
            foreach (ItemChange ic in ItemChanges)
            {
                if (ic.ChangeType == ChangeType.Create)
                {
                    Appointment lappointment = Appointment.Bind(LocalExchangeService, ic.ItemId);
                    Appointment rappointment = new Appointment(RemoteExchangeService);
                    rappointment.Subject = lappointment.Subject;
                    rappointment.Start = lappointment.Start;
                    rappointment.Body = lappointment.Body;
                    rappointment.End = lappointment.End;
                    rappointment.Location = lappointment.Location;
                    rappointment.Save();

                }

                else if (ic.ChangeType == ChangeType.Update)
                {
                    //Bind to the local appointment and get the start date
                    Appointment lappointment = Appointment.Bind(LocalExchangeService, ic.ItemId);
                    DateTime StartDate = lappointment.Start;
                    ItemId ItemToUpdate = ItemIDSearch(RemoteExchangeService,StartDate,lappointment.Subject);
                    //Bind to the remote appointment using ItemToUpdate & update all the details 
                    //this is is less intensive than comparing the appointments for changes.
                    Appointment rappointment = Appointment.Bind(RemoteExchangeService, ItemToUpdate);
                    rappointment.Subject = lappointment.Subject;
                    rappointment.Start = lappointment.Start;
                    rappointment.Body = lappointment.Body;
                    rappointment.End = lappointment.End;
                    rappointment.Location = lappointment.Location;
                    rappointment.Save();

                }
                else if (ic.ChangeType == ChangeType.Delete)
                {
                    Appointment lappointment = Appointment.Bind(LocalExchangeService, ic.ItemId.UniqueId);
                    DateTime StartDate = lappointment.Start;
                    ItemId ItemToUpdate = ItemIDSearch(RemoteExchangeService, StartDate, lappointment.Subject);
                    Appointment rappointment = Appointment.Bind(RemoteExchangeService, ic.ItemId.UniqueId);
                    rappointment.Delete(DeleteMode.MoveToDeletedItems);
                }

            }
        }


        return SyncState;
    }
    //End of Sync Method

    //Below method returns a single itemid from exchange service based on start datetime of an appointment in a mailbox.
    public ItemId ItemIDSearch(ExchangeService ExchangeService, DateTime AppointmentStart, string subject)
    {
        ItemId FoundItem;
        ItemView iv = new ItemView(1000);
        iv.Traversal = ItemTraversal.Associated;

        SearchFilter.SearchFilterCollection searchFilterCollection =  new SearchFilter.SearchFilterCollection(LogicalOperator.And);
        searchFilterCollection.Add(new SearchFilter.IsEqualTo(AppointmentSchema.Subject,subject));
        searchFilterCollection.Add(new SearchFilter.IsEqualTo(AppointmentSchema.Start, AppointmentStart));

        FindItemsResults<Item> fiitems = ExchangeService.FindItems(WellKnownFolderName.Calendar, searchFilterCollection, iv);

        if (fiitems.Items.Count == 1)//if we only get one result do the work else return null
        {
            FoundItem = fiitems.Items[0].Id;
        }

        FoundItem = null;

        return FoundItem;          
    }


}
    }

1 个答案:

答案 0 :(得分:3)

所有这一切的最终解决方案,来自Exchange Web Services的救世主Glen Scales,就是我在我的内部数据库中存储了与我同步的约会的“CleanGlobalObjectId”以及EWS UniqueId。调用EWS SyncFolderItems方法时返回。

使用作为约会的扩展属性的CleanGlobalObjectId,我总是能够在服务器上找到特定约会,即使它已被硬删除,因为此属性的值永远不会改变。