none
EWS Managed API: Deleting an impersonated appointment only by Id RRS feed

  • Question

  • Tested on a Microsoft Exchange 2007 SP 1 server with EWS.
     
    See the following code snippet:
    Question: why do I get an exception on the delete??? (Microsoft.Exchange.WebServices.Data.ServiceError.ErrorItemNotFound) "The specified object was not found in the store."
     
    Note: I successfully binded the appointment (see the check for the subject) so the appointment was "found" before the delete. And "contoso.com" is not the real domain, but for sake of argument.
      
    //superuser has all the rights..
    service.Credentials = new NetworkCredential("superuser", "xxxxxx"); ServicePointManager.ServerCertificateValidationCallback = delegate( object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true; }; service.AutodiscoverUrl("userToImpersonate@contoso.com", delegate(string redirectUrl) { return true; }); //method GetPrimaryEmailAddress return the primary address string primaryEmailAddress = GetPrimaryEmailAddress("userToImpersonate@contoso.com"); service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, primaryEmailAddress); Appointment appointement = new Appointment(service); string checkGuid = Guid.NewGuid().ToString("N"); appointement.Subject = checkGuid; appointement.Start = DateTime.Now; appointement.End = appointement.Start.AddMinutes(30); FolderId folderId = new FolderId(WellKnownFolderName.Calendar, new Mailbox(primaryEmailAddress)); appointement.Save(folderId,SendInvitationsMode.SendToNone); string uniqueId = appointement.Id.UniqueId; // so far, so good, now create another session, (in real situation: another process) ExchangeService anotherSessionService = new ExchangeService(ExchangeVersion.Exchange2007_SP1); anotherSessionService.Credentials = new NetworkCredential("superuser", "xxxxxx"); anotherSessionService.AutodiscoverUrl("superuser@contoso.com", delegate(string redirectUrl) { return true; }); ItemId anotherSessionItemId = new ItemId(uniqueId); Appointment anotherSessionAppointment = Appointment.Bind(anotherSessionService, anotherSessionItemId); // successfully got the appointment if(anotherSessionAppointment.Subject.Equals(checkGuid)) { // Exception!!??? anotherSessionAppointment.Delete(DeleteMode.HardDelete); }
    Wednesday, December 22, 2010 10:03 AM

Answers

  • Hello DickyDick,

    So, the Appointment.Bind did not throw an exception? That doesn't seem like correct behavior on the part of the API. It makes sense that the Appointment.Delete call failed but we shouldn't discover that the item doesn't exist in the target mailbox at that point. 

    The Appointment.Bind call in your code represents an attempt to access an item that does not exist in the callers mailbox. Capture the trace of the Appointment anotherSessionAppointment = Appointment.Bind(anotherSessionService, anotherSessionItemId); call and provide that to me (please remove all private information from the trace). I suspect that the XML will indicate that the item wasn't found and that the subsequent anotherSessionAppointment object has no properties set.

    You will have to use impersonation again since the ItemId does not have implied impersonation information associated with it as used by EWS. EWS does not perform a lookup for every item to determine which mailbox it is associated with and if impersonation permissions are granted for the calling account (the behavior for delegate access is different). EWS assumes the target ItemId (or FolderId) lookup is to be performed in the calling account's mailbox unless otherwise specified by either Exchange Impersonation or Delegate Access.

    As currently architected, your database will have to maintain mailbox/itemId information. There isn't a currently supported way to associate an ItemId to a mailbox with just the ItemId.

    With regards,


    Michael | Microsoft Exchange SDK

    The Exchange Development Forum Guide has useful information for using the Exchange Development Forum.

    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Monday, December 27, 2010 8:29 PM
    Moderator

All replies

  • Hello DickyDick,

    The reason why that is not working is that you aren't using Impersonation on your ExchangeService anotherSessionService object. Apply ImpersonatedUserId to the ExchangeService object. Otherwise, EWS is looking for the item in the callers account, not the impersonated account.

    With regards,


    Michael | Microsoft Exchange SDK

    The Exchange Development Forum Guide has useful information for using the Exchange Development Forum.

    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Wednesday, December 22, 2010 7:03 PM
    Moderator
  • Michael, Thanks for your time and reply!

    Remark: But you see that the appointment was fetched with the Bind!? That call succeeds and gives me a valid Appointment object. So it was "found". Why not fail there, instead of in the Delete? The "Appointment not found" exception is silly, because we have the object already!

    About your reply: Using again Impersonation, I was afraid of that. The matter is we only have the uniqueID. (stored in a database for later use)

    Quertion: Is there a way if we have Binded the appointment that we can programmatically retrieve the Mailbox of the Appointment, so we can impersonate it again. Perhaps by looking through parent folder(s) or likewise?

     

    Thursday, December 23, 2010 8:38 AM
  • Hello DickyDick,

    So, the Appointment.Bind did not throw an exception? That doesn't seem like correct behavior on the part of the API. It makes sense that the Appointment.Delete call failed but we shouldn't discover that the item doesn't exist in the target mailbox at that point. 

    The Appointment.Bind call in your code represents an attempt to access an item that does not exist in the callers mailbox. Capture the trace of the Appointment anotherSessionAppointment = Appointment.Bind(anotherSessionService, anotherSessionItemId); call and provide that to me (please remove all private information from the trace). I suspect that the XML will indicate that the item wasn't found and that the subsequent anotherSessionAppointment object has no properties set.

    You will have to use impersonation again since the ItemId does not have implied impersonation information associated with it as used by EWS. EWS does not perform a lookup for every item to determine which mailbox it is associated with and if impersonation permissions are granted for the calling account (the behavior for delegate access is different). EWS assumes the target ItemId (or FolderId) lookup is to be performed in the calling account's mailbox unless otherwise specified by either Exchange Impersonation or Delegate Access.

    As currently architected, your database will have to maintain mailbox/itemId information. There isn't a currently supported way to associate an ItemId to a mailbox with just the ItemId.

    With regards,


    Michael | Microsoft Exchange SDK

    The Exchange Development Forum Guide has useful information for using the Exchange Development Forum.

    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Monday, December 27, 2010 8:29 PM
    Moderator
  • Thanks for your reply. We will add the mailbox/itemid to indentify an appointment.

    It is a pity that the "uniqueId" is not system-wide.

     

    Monday, January 3, 2011 1:50 PM