我正在构建一个应用程序,该应用程序需要存在于受信任的域中,监视该域中的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;
}
}
}
答案 0 :(得分:3)
所有这一切的最终解决方案,来自Exchange Web Services的救世主Glen Scales,就是我在我的内部数据库中存储了与我同步的约会的“CleanGlobalObjectId”以及EWS UniqueId。调用EWS SyncFolderItems方法时返回。
使用作为约会的扩展属性的CleanGlobalObjectId,我总是能够在服务器上找到特定约会,即使它已被硬删除,因为此属性的值永远不会改变。