locked
How to delete Calendar Items using EWS RRS feed

  • Question

  • Hi all,

     

    I have a few calendars in one mail box.

    Using Exchange 2007 web services I can create/find calendars and add appointments

    But I can not delete any Items from these calendars.

    Original task can be found here. But I do not like that implementation.

    Originally I do not need to delete appointmens from default calendar. There ara plento of samples for default calendar.

     

    Before using DeleteItems method I have to create CalendarView, like this

     

    Code Snippet

                CalendarViewType cvCalendarVeiw = new CalendarViewType();
                cvCalendarVeiw.StartDate = start;
                cvCalendarVeiw.EndDate = end;
                cvCalendarVeiw.MaxEntriesReturned = 1000;
                cvCalendarVeiw.MaxEntriesReturnedSpecified = true;

                fiFindItemRequest.Item = cvCalendarVeiw;

     

    and include it in request.

     

    I have tried different codes (like this) but every time I got empty data in the following field

    RootFolder.TotalItemsInView = 0 or RootFolder = null

     

    I guess CalendarViewType retrieves data from default calendar only.

    My question is how to retrieve appointmets for the particular calendar (by name or folder id) using EWS in c# ?

    And after that (RootFolder.TotalItemsInView > 0) to delete it.

     

    Thanks in advance

    Saturday, November 22, 2008 8:00 AM

All replies

  • What are you using as the parent folder id in your Finditem call? 

    Sunday, November 23, 2008 2:25 PM
  • Code Snippet

    DistinguishedFolderIdType[] faFolderIDArray = new DistinguishedFolderIdType[2];

    faFolderIDArray[0] = new DistinguishedFolderIdType();

    faFolderIDArray[0].Id = DistinguishedFolderIdNameType.calendar;

    fiFindItemRequest.ParentFolderIds = faFolderIDArray;

     

     

    Monday, November 24, 2008 1:04 PM
  • Any idea ?

     

    Wednesday, November 26, 2008 11:58 AM
  • You mention non-default calendar folders, but the parent folder id you are using is for the default calendar folder.  Is there anything in your default calendar between the start/end date you specify?  If you want to do a calendar view against a non-default calendar folder, you need to pass in the FolderId for that specific calendar folder rather than using the DistinguishedFolderId.

     

    Also, if there are things in your calendar folder, you might want to remove the Calendar View and just do a normal Finditem to see if anything is returned there.  if so, maybe there is something strange with the dates that you are using for your calendar view.

    Wednesday, November 26, 2008 2:38 PM
  • Another thing - you are declaring your array to hold 2 folder ids, but you are only setting one.  Maybe you just didn't post all the code there but I figured it wouldn't hurt to point that out.

    Wednesday, November 26, 2008 2:40 PM
  • Of course, I know FolderItemId of my calendar. And this is not default calendar, definitely.

    fiFindItemRequest.ParentFolderIds does not allow to use or cast to my FolderItemId.

    It should be DistinguishedFolderIdType but not FolderItemIdType.

     

    As for array it does not metter I use only 0 index, but if you wish it could be like this:

    DistinguishedFolderIdType[] faFolderIDArray = new DistinguishedFolderIdType[1];

    and the result is the same - response has (RootFolder ==null)

     

    It should be another filter construction. But I do not know syntax, that is why I tried to use DistinguishedFolderIdType as generic type of my folder.

    Could you please provide correct sample of using DeleteItems method for non-default calendar entries?

    Here is my code, it does not work

    Code Snippet

    public void ClearAppointments(FolderIdType calendarFolder, DateTime start, DateTime end)

    {

    FindItemType fiFindItemRequest = new FindItemType();

    fiFindItemRequest.Traversal = ItemQueryTraversalType.Shallow;

    ItemResponseShapeType ipItemProperties = new ItemResponseShapeType();

    ipItemProperties.BaseShape = DefaultShapeNamesType.AllProperties;

    fiFindItemRequest.ItemShape = ipItemProperties;

    DistinguishedFolderIdType[] faFolderIDArray = new DistinguishedFolderIdType[1];

    faFolderIDArray[0] = new DistinguishedFolderIdType();

    faFolderIDArray[0].Id = DistinguishedFolderIdNameType.calendar;

    faFolderIDArray[0].Mailbox = new EmailAddressType();

    faFolderIDArray[0].Mailbox.EmailAddress = "calendarbox@local";

    fiFindItemRequest.ParentFolderIds = faFolderIDArray;

    CalendarViewType cvCalendarVeiw = new CalendarViewType();

    cvCalendarVeiw.StartDate = start;

    cvCalendarVeiw.EndDate = end;

    cvCalendarVeiw.MaxEntriesReturned = 1000;

    cvCalendarVeiw.MaxEntriesReturnedSpecified = true;

    fiFindItemRequest.Item = cvCalendarVeiw;

    System.Collections.ArrayList listOfIds = new System.Collections.ArrayList();

    FindItemResponseType frFindItemResponse = esb.FindItem(fiFindItemRequest);

    if (frFindItemResponse != null)

    {

    ResponseMessageType a1 = frFindItemResponse.ResponseMessages.Items[0];

    ArrayOfRealItemsType root = (ArrayOfRealItemsType)((FindItemResponseMessageType)(a1)).RootFolder.Item;

    if (root.Items != null)

    {

    foreach (ItemType item in root.Items)

    {

    listOfIds.Add(item.ItemId);

    }

    }

    foreach (ItemIdType itemId in listOfIds)

    {

    DeleteItemType diDeleteItemRequest = new DeleteItemType();

    BaseItemIdType[] itemIdToDelete = new BaseItemIdType[1];

    itemIdToDelete[0] = itemId;

    diDeleteItemRequest.ItemIds = itemIdToDelete;

    diDeleteItemRequest.DeleteType = DisposalType.HardDelete;

    diDeleteItemRequest.SendMeetingCancellationsSpecified = true;

    diDeleteItemRequest.AffectedTaskOccurrencesSpecified = true;

    diDeleteItemRequest.AffectedTaskOccurrences = AffectedTaskOccurrencesType.AllOccurrences;

     

    diDeleteItemRequest.SendMeetingCancellations = CalendarItemCreateOrDeleteOperationType.SendToNone;

    DeleteItemResponseType diResponse = esb.DeleteItem(diDeleteItemRequest);

    }

    }

    }

     

    Thursday, November 27, 2008 6:01 AM
  • Up

     

    Friday, November 28, 2008 1:07 PM
  • I think FindItem does not work properly with not default calendars. I tried different samples like this. No chance.

    Then I tried to use GetFolder method. As I know FolderId, I can pass it to my void. But I do not know how to retrieve CalendarItems collection.

    If I pass my CalendarFolder as findItemRequest.ParentFolderIds it is compiled and succesfully create CalendarFolderType calendar instance

    But I have got exceptons on esb.FindItem(findItemRequest)

    This is the most stupid object model which I have ever seen

    Please help.

     

    Code Snippet

    public void ClearAppointments(FolderIdType calendarFolder, DateTime start, DateTime end)

    {

    // Identify the folder properties to return.

    FolderResponseShapeType properties = new FolderResponseShapeType();

    PathToUnindexedFieldType ptuft = new PathToUnindexedFieldType();

    ptuft.FieldURI = UnindexedFieldURIType.folderManagedFolderInformation;

    PathToUnindexedFieldType[] ptufts = new PathToUnindexedFieldType[1] { ptuft };

    properties.AdditionalProperties = ptufts;

    properties.BaseShape = DefaultShapeNamesType.AllProperties;

    // Form the get folder request.

    GetFolderType request = new GetFolderType();

    request.FolderIds = new BaseFolderIdType[1] { calendarFolder };

    request.FolderShape = properties;

     

    CalendarViewType cvCalendarVeiw = new CalendarViewType();

    cvCalendarVeiw.StartDate = start;

    cvCalendarVeiw.EndDate = end;

    cvCalendarVeiw.MaxEntriesReturned = 1000;

    cvCalendarVeiw.MaxEntriesReturnedSpecified = true;

     

    try

    {

    // Send the request and get the resp.

    GetFolderResponseType resp = esb.GetFolder(request);

    ArrayOfResponseMessagesType aormt = resp.ResponseMessages;

    ResponseMessageType[] rmta = aormt.Items;

    foreach (ResponseMessageType rmt in rmta)

    {

    if (rmt.ResponseClass == ResponseClassType.Success)

    {

    FolderInfoResponseMessageType firmt;

    firmt = (rmt as FolderInfoResponseMessageType);

    BaseFolderType[] folders = firmt.Folders;

    foreach (BaseFolderType folder in folders)

    {

    if (folder is CalendarFolderType)

    {

    CalendarFolderType calendar = (folder as CalendarFolderType);

    Console.Write(calendar.ParentFolderId.Id);

    FindItemType findItemRequest = new FindItemType();

    //I think it is not correct but I have now other solution

    findItemRequest.ParentFolderIds = new FolderIdType[] { calendar.FolderId };

    findItemRequest.Traversal = ItemQueryTraversalType.Shallow;

    findItemRequest.Item = cvCalendarVeiw;

    FindItemResponseType findItemResponse = esb.FindItem(findItemRequest);

    if (findItemResponse != null)

    {

    ResponseMessageType a1 = findItemResponse.ResponseMessages.Items[0];

    ArrayOfRealItemsType root = (ArrayOfRealItemsType)((FindItemResponseMessageType)(a1)).RootFolder.Item;

    System.Collections.ArrayList listOfIds = new System.Collections.ArrayList();

    if (root.Items != null)

    {

    foreach (ItemType item in root.Items)

    {

    listOfIds.Add(item.ItemId);

    }

    }

    foreach (ItemIdType itemId in listOfIds)

    {

    DeleteItemType diDeleteItemRequest = new DeleteItemType();

    BaseItemIdType[] itemIdToDelete = new BaseItemIdType[1];

    itemIdToDelete[0] = itemId;

    diDeleteItemRequest.ItemIds = itemIdToDelete;

    diDeleteItemRequest.DeleteType = DisposalType.HardDelete;

    diDeleteItemRequest.SendMeetingCancellationsSpecified = true;

    diDeleteItemRequest.AffectedTaskOccurrencesSpecified = true;

    diDeleteItemRequest.AffectedTaskOccurrences = AffectedTaskOccurrencesType.AllOccurrences;

     

    diDeleteItemRequest.SendMeetingCancellations = CalendarItemCreateOrDeleteOperationType.SendToNone;

    DeleteItemResponseType diResponse = esb.DeleteItem(diDeleteItemRequest);

    }

     

    }

     

     

    }

    }

    }

    }

    }

    catch (Exception e)

    {

    Console.Write(e.Message);

    }

    }

     

     

    Monday, December 1, 2008 12:36 PM
  • Here is an example app that creates a non default calendar, creates a recurring appointment in that calendar and then uses FindItem to find all recurrences is a 10 day range (or something like that).  Just as an aside - the "object model" is autogenerated by the visual studio proxy generator (or the WCF one depending on which you are using).  So there is certainly a whole bunch of client side logic that is lacking due to the fact that the proxy generators truly have no idea what you want to do with it.  It would be better for you to think of the proxy generated classes as XML generators rather than as an API in and of itself.  The contract is XML based. 

     

    Note that at PDC 2008 we just announced our managed API which will support both Exchange 2007 SP1 and the next version of Exchange.  It has a bunch of client side smarts and reduces the amount of code you have to write significantly.  Not sure what the official public date of it is right now.

     

    Anyways, here is the example.  Hope it helps.

     

    class Program

    {

       private static ExchangeServiceBinding binding;

       static void Main(string[] args)

       {

          System.Net.ServicePointManager.ServerCertificateValidationCallback =

             delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)

             {

                  return true;

             };

             InitializeService();

             FolderIdType calendarFolder = CreateNonDefaultCalendarFolder();

             CreateItemInNonDefaultCalendarFolder(calendarFolder);

             CallFindItemOnNonDefaultCalendar(calendarFolder);

       }

     

       private static void CallFindItemOnNonDefaultCalendar(FolderIdType folderId)

       {

          FindItemType request = new FindItemType();

          request.ParentFolderIds = new BaseFolderIdType[] { folderId };

          request.ItemShape = new ItemResponseShapeType();

          request.ItemShape.BaseShape = DefaultShapeNamesType.Default;

          request.Traversal = ItemQueryTraversalType.Shallow;

          CalendarViewType paging = new CalendarViewType();

          paging.StartDate = DateTime.Now.AddDays(-1d);

          paging.EndDate = paging.StartDate.AddDays(10d);

          paging.MaxEntriesReturned = 100;

          paging.MaxEntriesReturnedSpecified = true;

          request.Item = paging;

          FindItemResponseType response = binding.FindItem(request);

          FindItemResponseMessageType responseMessage = response.ResponseMessages.Items[0] as   

               FindItemResponseMessageType;

          if (responseMessage.ResponseCode != ResponseCodeType.NoError)

          {

              throw new Exception(responseMessage.MessageText);

          }

          Console.WriteLine("Found " + responseMessage.RootFolder.TotalItemsInView + " items");

          ArrayOfRealItemsType items = responseMessage.RootFolder.Item as ArrayOfRealItemsType;

          foreach (CalendarItemType calendarItem in items.Items)

          {

              Console.WriteLine(String.Format("Start: {0}, End: {1})", calendarItem.Start, calendarItem.End));

          }

       }

     

    private static void CreateItemInNonDefaultCalendarFolder(FolderIdType folderId)

    {

    CreateItemType request = new CreateItemType();

    request.MessageDisposition = MessageDispositionType.SaveOnly;

    request.MessageDispositionSpecified = true;

    request.SendMeetingInvitations = CalendarItemCreateOrDeleteOperationType.SendToNone;

    request.SendMeetingInvitationsSpecified = true;

    request.SavedItemFolderId = new TargetFolderIdType();

    request.SavedItemFolderId.Item = folderId;

    request.Items = new NonEmptyArrayOfAllItemsType();

    CalendarItemType calendarItem = new CalendarItemType();

    calendarItem.Subject = "My recurring item";

    calendarItem.Start = DateTime.Now;

    calendarItem.StartSpecified = true;

    calendarItem.End = DateTime.Now.AddHours(1d);

    calendarItem.EndSpecified = true;

    DailyRecurrencePatternType recurrencePattern = new DailyRecurrencePatternType();

    recurrencePattern.Interval = 2;

    EndDateRecurrenceRangeType recurrenceRange = new EndDateRecurrenceRangeType();

    recurrenceRange.StartDate = calendarItem.Start;

    recurrenceRange.EndDate = calendarItem.Start.AddMonths(2);

    calendarItem.Recurrence = new RecurrenceType();

    calendarItem.Recurrence.Item = recurrencePattern;

    calendarItem.Recurrence.Item1 = recurrenceRange;

    request.Items.Items = new ItemType[] { calendarItem };

    CreateItemResponseType response = binding.CreateItem(request);

    ItemInfoResponseMessageType responseMessage = response.ResponseMessages.Items[0] as ItemInfoResponseMessageType;

    if (responseMessage.ResponseCode != ResponseCodeType.NoError)

    {

    throw new Exception(responseMessage.MessageText);

    }

    Console.WriteLine("Created calendar item : " + responseMessage.Items.Items[0].ItemId.Id);

    }

     

     

    private static FolderIdType CreateNonDefaultCalendarFolder()

    {

    CalendarFolderType calendarFolder = new CalendarFolderType();

    calendarFolder.DisplayName = "My Non-Default Calendar-" + Environment.TickCount;

    CreateFolderType request = new CreateFolderType();

    request.Folders = new BaseFolderType[] { calendarFolder };

    DistinguishedFolderIdType parentFolder = new DistinguishedFolderIdType();

    parentFolder.Id = DistinguishedFolderIdNameType.msgfolderroot;

    request.ParentFolderId = new TargetFolderIdType();

    request.ParentFolderId.Item = parentFolder;

    CreateFolderResponseType response = binding.CreateFolder(request);

    FolderInfoResponseMessageType responseMessage = response.ResponseMessages.Items[0] as FolderInfoResponseMessageType;

    if (responseMessage.ResponseCode != ResponseCodeType.NoError)

    {

    throw new Exception(responseMessage.MessageText);

    }

    return responseMessage.Folders[0].FolderId;

    }

     

    /// <summary>

    /// Initialize the ExchangeServer using URL and Username/Password/Domain tuple

    /// </summary>

    private static void InitializeService()

    {

    binding = new ExchangeServiceBinding();

    binding.Url = "https://server/ews/Exchange.asmx";

    binding.Credentials = new System.Net.NetworkCredential("Administrator", "password", "domain");

    }

     

     

    Monday, December 1, 2008 3:43 PM
  • Hi David,

    Thank you very much, I am so appreciate you for the sample.

    Especially for this casting hint:

    Code Snippet

    FindItemResponseMessageType responseMessage = response.ResponseMessages.Items[0] as   

               FindItemResponseMessageType;

    Definitely, it was not obvious.

     

    At least it works. Here is my working method:

    Code Snippet

    public void DeleteNonDefaultCalendarFolderAppointments(FolderIdType folderId, DateTime start, DateTime end)

    {

    FindItemType request = new FindItemType();

    request.ParentFolderIds = new BaseFolderIdType[] { folderId };

    request.ItemShape = new ItemResponseShapeType();

    request.ItemShape.BaseShape = DefaultShapeNamesType.Default;

    request.Traversal = ItemQueryTraversalType.Shallow;

    CalendarViewType paging = new CalendarViewType();

    paging.StartDate = start;

    paging.EndDate = end;

    paging.MaxEntriesReturned = 1000;

    paging.MaxEntriesReturnedSpecified = true;

    request.Item = paging;

    FindItemResponseType response = esb.FindItem(request);

    FindItemResponseMessageType responseMessage = response.ResponseMessages.Items[0] as FindItemResponseMessageType;

    if (responseMessage.ResponseCode != ResponseCodeType.NoError)

    {

    throw new Exception(responseMessage.MessageText);

    }

    if (responseMessage.RootFolder.TotalItemsInView > 0)

    {

    Console.WriteLine("Found " + responseMessage.RootFolder.TotalItemsInView + " items");

    ArrayOfRealItemsType items = responseMessage.RootFolder.Item as ArrayOfRealItemsType;

    if (items.Items != null)

    {

    BaseItemIdType[] itemIdToDelete = new BaseItemIdType[items.Items.Length];

    int index = 0;

    foreach (CalendarItemType calendarItem in items.Items)

    {

    Console.WriteLine(String.Format("Start: {0}, End: {1})", calendarItem.Start, calendarItem.End));

    itemIdToDelete[index] = calendarItem.ItemId;

    index++;

    }

    DeleteItemType diDeleteItemRequest = new DeleteItemType();

    diDeleteItemRequest.ItemIds = itemIdToDelete;

    diDeleteItemRequest.DeleteType = DisposalType.HardDelete;

    diDeleteItemRequest.SendMeetingCancellationsSpecified = true;

    diDeleteItemRequest.AffectedTaskOccurrencesSpecified = true;

    diDeleteItemRequest.AffectedTaskOccurrences = AffectedTaskOccurrencesType.AllOccurrences;

    diDeleteItemRequest.SendMeetingCancellations = CalendarItemCreateOrDeleteOperationType.SendToNone;

    DeleteItemResponseType diResponse = esb.DeleteItem(diDeleteItemRequest);

    }

    }

    }

     

     

    Tuesday, December 2, 2008 12:42 PM
  • I agree that the cast is not obvious.  That is an unfortunate byproduct of the proxy classes.  The schema should help some with that, although most people don't like looking at xsd and wsdl files Smile  The client API (when it becomes available) will rectify all of that as it hides all these complexities.  Glad it worked for you.

    Tuesday, December 2, 2008 2:14 PM