24

我们为在Exchange 2007公用文件夹中设置的公司设置公共日历。我可以使用下面的代码检索当天的个人日历约会。我在网上搜索了高和低,我找不到某人从公共文件夹日历中检索日历信息的示例。使用Exchange Web服务API提取Exchange 2007公共日历约会

它似乎应该是可行的,但我不能为我的生活得到它的工作。我如何修改下面的代码来访问日历?我不想通过asp.net创建任何约会,只需检索一个简单的列表。我也接受任何其他建议。谢谢。

ADDED BOUNTY
- 我不能有史以来需要做到这一点的唯一的人。让我们为后代解决这个问题。

再次更新由于无知
- 我忘了,我工作的项目是.NET 2.0(非常重要的你不觉得?)。

*将我的代码解决方案BELOW *
- 我已经取代与结束了工作的代码我原来的代码示例。非常感谢Oleg提供的代码来查找公用文件夹,这是最难的部分..我使用这里的例子修改了代码http://msexchangeteam.com/archive/2009/04/21/451126.aspx以使用更简单的FindAppointments方法。

这个简单的例子返回一个html字符串与约会,但你可以使用它作为一个基础,根据需要进行自定义。你可以在下面的答案中看到我们的来回。

using System; 
using Microsoft.Exchange.WebServices.Data; 
using System.Net; 

namespace ExchangePublicFolders 
{ 
    public class Program 
    { 
     public static FolderId FindPublicFolder(ExchangeService myService, FolderId baseFolderId, 
     string folderName) 
     { 

     FolderView folderView = new FolderView(10, 0); 
     folderView.OffsetBasePoint = OffsetBasePoint.Beginning; 
     folderView.PropertySet = new PropertySet(FolderSchema.DisplayName, FolderSchema.Id); 

     FindFoldersResults folderResults; 
     do 
     { 
      folderResults = myService.FindFolders(baseFolderId, folderView); 

      foreach (Folder folder in folderResults) 
       if (String.Compare(folder.DisplayName, folderName, StringComparison.OrdinalIgnoreCase) == 0) 
        return folder.Id; 

      if (folderResults.NextPageOffset.HasValue) 
       folderView.Offset = folderResults.NextPageOffset.Value; 
     } 
     while (folderResults.MoreAvailable); 

     return null; 
    } 

    public static string MyTest() 
    { 
     ExchangeService myService = new ExchangeService(ExchangeVersion.Exchange2007_SP1); 

     myService.Credentials = new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN"); 
     myService.Url = new Uri("https://MAILSERVER/ews/exchange.asmx"); 

     Folder myPublicFoldersRoot = Folder.Bind(myService, WellKnownFolderName.PublicFoldersRoot); 
     string myPublicFolderPath = @"PUBLIC_FOLDER_CALENDAR_NAME"; 
     string[] folderPath = myPublicFolderPath.Split('\\'); 
     FolderId fId = myPublicFoldersRoot.Id; 
     foreach (string subFolderName in folderPath) 
     { 
      fId = Program.FindPublicFolder(myService, fId, subFolderName); 
      if (fId == null) 
      { 
       return string.Format("ERROR: Can't find public folder {0}", myPublicFolderPath); 

      } 
     } 

     Folder folderFound = Folder.Bind(myService, fId); 
     if (String.Compare(folderFound.FolderClass, "IPF.Appointment", StringComparison.Ordinal) != 0) 
     { 
      return string.Format("ERROR: Public folder {0} is not a Calendar", myPublicFolderPath); 

     } 

     CalendarFolder AK_Calendar = CalendarFolder.Bind(myService, fId, BasePropertySet.FirstClassProperties); 

     FindItemsResults<Appointment> AK_appointments = AK_Calendar.FindAppointments(new CalendarView(DateTime.Now,DateTime.Now.AddDays(1))); 


     string rString = string.Empty; 


     foreach (Appointment AK_appoint in AK_appointments) 
     { 

      rString += string.Format("Subject: {0}<br />Date: {1}<br /><br />", AK_appoint.Subject, AK_appoint.Start);  
     } 

     return rString; 
    } 

    } 
} 
+0

嗨!代码'FindItemsResults '看起来不错。在我看来,你忘记为'CalendarView'设置'PropertySet'。这很重要。如果您只使用搜索结果中的“约会”和“开始”约会属性,则应该设置这两个属性“ItemSchema.Subject”和“AppointmentSchema.Start”。如果你不这样做,所有'PropertySet.FirstClassProperties'将从Exchange服务器发送。我包括在文件夹绑定这个属性集只显示有多少。此外,我建议你继续使用分页。 – Oleg 2010-09-14 21:49:16

+0

顺便说一下'ItemView'和'FindItemsResults '的用法是因为我修改了另一个枚举电子邮件的例子。在邮箱文件夹中,您不仅可以找到**电子邮件,还可以找到符合预约的要求。所以要枚举邮箱,最好使用基类“Item”。看起来,用日历文件夹你不会有问题,但想想这个可能的问题。最好的问候和祝你好运! – Oleg 2010-09-14 21:54:46

+0

@Oleg我将继续分页。我把PropertySet关闭了,因为我想玩弄所有的属性。一旦我确定了我想要使用的属性,我将添加它。我现在只会坚持使用日历,但如果需要访问电子邮箱,我将使用Itemview。 – NinjaBomb 2010-09-15 02:46:03

回答

15

就像这里承诺的是一个代码示例。我使用the Microsoft Exchange Web Services (EWS) Managed API 1.0并建议您也这样做。我在代码中包含

using System; 
using Microsoft.Exchange.WebServices.Data; 
using System.Net; 

namespace ExchangePublicFolders { 
    class Program { 
     static FolderId FindPublicFolder (ExchangeService myService, FolderId baseFolderId, 
      string folderName) { 

      // We will search using paging. We will use page size 10 
      FolderView folderView = new FolderView (10,0); 
      folderView.OffsetBasePoint = OffsetBasePoint.Beginning; 
      // we will need only DisplayName and Id of every folder 
      // se we'll reduce the property set to the properties 
      folderView.PropertySet = new PropertySet (FolderSchema.DisplayName, 
       FolderSchema.Id); 

      FindFoldersResults folderResults; 
      do { 
       folderResults = myService.FindFolders (baseFolderId, folderView); 

       foreach (Folder folder in folderResults) 
        if (String.Compare (folder.DisplayName, folderName, StringComparison.OrdinalIgnoreCase) == 0) 
         return folder.Id; 

       if (folderResults.NextPageOffset.HasValue) 
        // go to the next page 
        folderView.Offset = folderResults.NextPageOffset.Value; 
      } 
      while (folderResults.MoreAvailable); 

      return null; 
     } 

     static void MyTest() { 
      // IMPORTANT: ExchangeService is NOT thread safe, so one should create an instance of 
      // ExchangeService whenever one needs it. 
      ExchangeService myService = new ExchangeService (ExchangeVersion.Exchange2007_SP1); 

      myService.Credentials = new NetworkCredential ("[email protected]", "myPassword00"); 
      myService.Url = new Uri ("http://mailwebsvc-t.services.local/ews/exchange.asmx"); 
      // next line is very practical during development phase or for debugging 
      myService.TraceEnabled = true; 

      Folder myPublicFoldersRoot = Folder.Bind (myService, WellKnownFolderName.PublicFoldersRoot); 
      string myPublicFolderPath = @"OK soft GmbH (DE)\Gruppenpostfächer\_Template - Gruppenpostfach\_Template - Kalender"; 
      string[] folderPath = myPublicFolderPath.Split('\\'); 
      FolderId fId = myPublicFoldersRoot.Id; 
      foreach (string subFolderName in folderPath) { 
       fId = FindPublicFolder (myService, fId, subFolderName); 
       if (fId == null) { 
        Console.WriteLine ("ERROR: Can't find public folder {0}", myPublicFolderPath); 
        return; 
       } 
      } 

      // verify that we found 
      Folder folderFound = Folder.Bind (myService, fId); 
      if (String.Compare (folderFound.FolderClass, "IPF.Appointment", StringComparison.Ordinal) != 0) { 
       Console.WriteLine ("ERROR: Public folder {0} is not a Calendar", myPublicFolderPath); 
       return; 
      } 

      CalendarFolder myPublicFolder = CalendarFolder.Bind (myService, 
       //WellKnownFolderName.Calendar, 
       fId, 
       PropertySet.FirstClassProperties); 

      if (myPublicFolder.TotalCount == 0) { 
       Console.WriteLine ("Warning: Public folder {0} has no appointment. We try to create one.", myPublicFolderPath); 

       Appointment app = new Appointment (myService); 
       app.Subject = "Writing a code example"; 
       app.Start = new DateTime (2010, 9, 9); 
       app.End = new DateTime (2010, 9, 10); 
       app.RequiredAttendees.Add ("[email protected]"); 
       app.Culture = "de-DE"; 
       app.Save (myPublicFolder.Id, SendInvitationsMode.SendToNone); 
      } 

      // We will search using paging. We will use page size 10 
      ItemView viewCalendar = new ItemView (10); 
      // we can include all properties which we need in the view 
      // If we comment the next line then ALL properties will be 
      // read from the server. We can see there in the debug output 
      viewCalendar.PropertySet = new PropertySet (ItemSchema.Subject); 
      viewCalendar.Offset = 0; 
      viewCalendar.OffsetBasePoint = OffsetBasePoint.Beginning; 
      viewCalendar.OrderBy.Add (ContactSchema.DateTimeCreated, SortDirection.Descending); 

      FindItemsResults<Item> findResultsCalendar; 
      do { 
       findResultsCalendar = myPublicFolder.FindItems (viewCalendar); 

       foreach (Item item in findResultsCalendar) { 
        if (item is Appointment) { 
         Appointment appoint = item as Appointment; 
         Console.WriteLine ("Subject: \"{0}\"", appoint.Subject); 
        } 
       } 

       if (findResultsCalendar.NextPageOffset.HasValue) 
        // go to the next page 
        viewCalendar.Offset = findResultsCalendar.NextPageOffset.Value; 
      } 
      while (findResultsCalendar.MoreAvailable); 
     } 
     static void Main (string[] args) { 
      MyTest(); 
     } 
    } 
} 

最多评论您应该更新字符串myPublicFolderPath与您的公共文件夹压延机的价值。我设置了myService.TraceEnabled = true,它可以产生带有调试信息的长输出。您应该删除生产线。

已更新:您可以在Create new calendar system support in Exchange OWA中找到一些其他链接。如果您还没有看到视频,并且您想使用Exchange Web服务,我会建议您在那里观看。它可以节省你的时间在未来。

+0

谢谢!我在我的问题中遗漏了一条非常重要的信息。我的项目停留在.NET 2.0上。对于那个很抱歉。既然这是我的错,你提供的解决方案非常全面,需要一些时间来放在一起,我会给你赏金。既然我不能在不升级的情况下将dll添加到项目中,你会怎么做?我的第一个想法是有一个完全独立的网站提供Web服务来提取日历数据,但这听起来像是矫枉过正。你怎么看? – NinjaBomb 2010-09-10 13:11:15

+0

@NinjaBomb:如果您查看产生我的测试程序('myService.TraceEnabled = true')的调试输出,您可以看到EWS托管API 1.0发送了您可以通过WebProxy发送的相同请求。例如,查看http://msdn.microsoft.com/en-us/library/aa493892(v=EXCHG.140).aspx。你可以不使用'FolderQueryTraversalType.Deep'作为公共文件夹,但是你可以很容易地修改代码,使它和我的程序中的FindPublicFolder一样。 – Oleg 2010-09-10 13:41:57

+0

@NinjaBomb:查看http://msdn.microsoft.com/en-us/library/bb402172(v=EXCHG.140).aspx和http://msdn.microsoft.com/en-us/ library/aa563918(v = EXCHG.140).aspx等,您可以在EWS中找到相应的代码示例作为代理(请参阅http://msdn.microsoft.com/en-us/library/exchangewebservices(v=EXCHG。 140).aspx)并实现您的程序。另请参阅Exchange Web服务操作(网址:http://msdn.microsoft.com/zh-cn/library/bb409286(v=EXCHG.140).aspx) – Oleg 2010-09-10 13:43:43

1
+0

感谢您的链接。我已经看到geekswithblogs.net文章在我执行的每个搜索中搜索公共文件夹。除非我完全错过了它,否则我没有看到他实际上从公共文件夹日历中取出任何日历约会。我将检查WebDAV方法,但我没有发现它用于Exchange 2007日历的任何示例,或者它的工作原理。 – NinjaBomb 2010-09-08 03:47:47

+0

WebDAV已弃用且未包含在Exchange 2010中(请参阅http://msdn.microsoft.com/zh-cn/library/dd877032.aspx)。一个可以使用Exchange Web服务访问Exchange 2007公用文件夹。如果我能找到一点时间,我会稍后发布一个例子。 – Oleg 2010-09-08 15:20:58

+0

奥列格你发布了一个很好的例子,从一个公共文件夹日历拉我的工作,并得到赏金的一个很好的例子的答案!我仔细查看了Microsoft为Exchange Web Services提供的每个示例,但都没有涉及公用文件夹。我会尽快测试你发布的任何内容。 – NinjaBomb 2010-09-08 21:11:47

相关问题