3

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

我遇到的问题是我无法找到跟踪远程约会的方法,以便在必要时更新或删除它。在远程服务器上创建约会后,他们有一个新的 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;          
    }


}
    }
4

1 回答 1

3

因此,来自 Exchange Web 服务的救星 Glen Scales 的所有这一切的最终解决方案是,我将正在同步的约会的“CleanGlobalObjectId”与调用时返回的 EWS UniqueId 一起存储在我的内部数据库中EWS SyncFolderItems 方法。

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

于 2012-08-06T11:47:27.237 回答