EWS: "Set action invalid for property" when editing RequiredAttendees

Before closing this as a duplicate, please look at another similarly titled question, there is no answer to the problem, which he simply marked as the answer and left.

I get this beautiful and descriptive error from the EWS managed API whenever I try to edit the RequiredAttendees property in a meeting.

Set action is invalid for property.

Looking at the details of the exception, I see that this RequiredAttendees property is really causing problems, but I have no idea why.

The credentials that I use to connect to the service belong to the meeting organizer, I even tried to impersonate a person without any luck. He scratched my head, trying to figure out what was wrong here.

Here are the relevant parts of the upgrade procedure that cause problems.

 PropertySet props = new PropertySet( AppointmentSchema.Start, AppointmentSchema.End, AppointmentSchema.Id, AppointmentSchema.Organizer, AppointmentSchema.Subject, AppointmentSchema.Body, AppointmentSchema.RequiredAttendees); props.RequestedBodyType = BodyType.Text; Appointment appointment = Appointment.Bind(_service, new ItemId(appointmentId), props); if (IsResource(appointment.Organizer.Address) && appointment.Organizer.Address != resourceId) { /* * removed for brevity, no attendee manipulation here */ } else { List<Attendee> remove = new List<Attendee>(); foreach (var attendee in appointment.RequiredAttendees) { if (IsResource(attendee.Address) && attendee.Address != resourceId) { remove.Add(attendee); } } remove.ForEach(a => appointment.RequiredAttendees.Remove(a)); if (!appointment.RequiredAttendees.Any(a => a.Address == resourceId)) { appointment.RequiredAttendees.Add(resourceId); } } /* * removed for brevity, no attendee manipulation here */ if (IsAvailable(resourceId, startTime, endTime, appointmentId)) appointment.Update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToAllAndSaveCopy); else throw new RoomUnavailableException(); 

Request:

 <Trace Tag = "EwsRequest" Tid="14" Time="2017-09-25 20:20:24Z" Version="15.00.0847.030"> <?xml version = "1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <t:RequestServerVersion Version = "Exchange2013" /> </ soap:Header> <soap:Body> <m:UpdateItem ConflictResolution = "AlwaysOverwrite" SendMeetingInvitationsOrCancellations="SendToAllAndSaveCopy"> <m:ItemChanges> <t:ItemChange> <t:ItemId Id = "AAMkAGEwYWRjZjA3LWNlZjAtNDI2Ny05ZjQwLWUzYWZjOThhMjkzNwBGAAAAAABWdX+yf6THTpO/1LYpoG6xBwD6lEwS6u8XQbDhIlTh/X/UAAAAAAENAAD6lEwS6u8XQbDhIlTh/X/UAAAi3oSdAAA=" ChangeKey="DwAAABYAAAD6lEwS6u8XQbDhIlTh/X/UAAAi3ocU" /> <t:Updates> <t:SetItemField> <t:FieldURI FieldURI = "calendar:RequiredAttendees" /> < t:CalendarItem> <t:RequiredAttendees> <t:Attendee> <t:Mailbox> <t:Name>Exchange Test</t:Name> <t:EmailAddress>etest @supertester.com</t:EmailAddress> <t:RoutingType>SMTP</t:RoutingType> <t:MailboxType>Mailbox</t:MailboxType> </t:Mailbox> </t:Attendee> <t:Attendee> <t:Mailbox> <t:EmailAddress>redroom @supertester.com</t:EmailAddress> </t:Mailbox> </t:Attendee> </t:RequiredAttendees> </t:CalendarItem> </t:SetItemField> </t:Updates> </t:ItemChange> </m:ItemChanges> </m:UpdateItem> </soap:Body> </soap:Envelope> </Trace> + yf6THTpO / 1LYpoG6xBwD6lEwS6u8XQbDhIlTh / X / UAAAAAAENAAD6lEwS6u8XQbDhIlTh / X / UAAAi3oSdAAA =" ChangeKey = "DwAAABYAAAD6lEwS6u8XQbDhIlTh / X / UAAAi3ocU" /> <Trace Tag = "EwsRequest" Tid="14" Time="2017-09-25 20:20:24Z" Version="15.00.0847.030"> <?xml version = "1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <t:RequestServerVersion Version = "Exchange2013" /> </ soap:Header> <soap:Body> <m:UpdateItem ConflictResolution = "AlwaysOverwrite" SendMeetingInvitationsOrCancellations="SendToAllAndSaveCopy"> <m:ItemChanges> <t:ItemChange> <t:ItemId Id = "AAMkAGEwYWRjZjA3LWNlZjAtNDI2Ny05ZjQwLWUzYWZjOThhMjkzNwBGAAAAAABWdX+yf6THTpO/1LYpoG6xBwD6lEwS6u8XQbDhIlTh/X/UAAAAAAENAAD6lEwS6u8XQbDhIlTh/X/UAAAi3oSdAAA=" ChangeKey="DwAAABYAAAD6lEwS6u8XQbDhIlTh/X/UAAAi3ocU" /> <t:Updates> <t:SetItemField> <t:FieldURI FieldURI = "calendar:RequiredAttendees" /> < t:CalendarItem> <t:RequiredAttendees> <t:Attendee> <t:Mailbox> <t:Name>Exchange Test</t:Name> <t:EmailAddress>etest @supertester.com</t:EmailAddress> <t:RoutingType>SMTP</t:RoutingType> <t:MailboxType>Mailbox</t:MailboxType> </t:Mailbox> </t:Attendee> <t:Attendee> <t:Mailbox> <t:EmailAddress>redroom @supertester.com</t:EmailAddress> </t:Mailbox> </t:Attendee> </t:RequiredAttendees> </t:CalendarItem> </t:SetItemField> </t:Updates> </t:ItemChange> </m:ItemChanges> </m:UpdateItem> </soap:Body> </soap:Envelope> </Trace> 

Response Tracking:

 <Trace Tag = "EwsResponse" Tid="14" Time="2017-09-25 20:20:24Z" Version="15.00.0847.030"> <?xml version = "1.0" encoding="utf-8"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Header> <h:ServerVersionInfo MajorVersion = "15" MinorVersion="1" MajorBuildNumber="225" MinorBuildNumber="41" Version="V2_48" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /> </s:Header> <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <m:UpdateItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> <m:ResponseMessages> <m:UpdateItemResponseMessage ResponseClass = "Error" > <m:MessageText>Set action is invalid for property.</m:MessageText> <m:ResponseCode>ErrorInvalidPropertySet</m:ResponseCode> <m:DescriptiveLinkKey>0</m:DescriptiveLinkKey> <m:MessageXml> <t:FieldURI FieldURI = "calendar:RequiredAttendees" /> </m:MessageXml> <m:Items /> </m:UpdateItemResponseMessage> </m:ResponseMessages> </m:UpdateItemResponse> </s:Body> </s:Envelope> </Trace> 
+5
source share
2 answers

Many thanks to Glen Scales for pointing me in the right direction.

When I received the meetings, I used the following code:

 CalendarFolder calendar = CalendarFolder.Bind(_service, new FolderId(WellKnownFolderName.Calendar, resourceId), PropertySet.IdOnly); CalendarView cView = new CalendarView(startDate, endDate, _maxAppointments); cView.PropertySet = new PropertySet(PropertySet.IdOnly); FindItemsResults<Appointment> appointments = calendar.FindAppointments(cView); 

Where resourceId was the mailbox address of the room, not the meeting organizer.

Editing participants in a meeting that is not the original is not allowed, so this is what gave me the error. To update the participants, I have to get the appointment of the organizers with the following code (heavily borrowed from this post ):

 appointment = FindOrganizerAppointment(appointment); /// <summary> /// Finds the related Appointment. /// </summary> /// <param name="appointment">The appointment whose original is to be found.</param> /// <returns></returns> private Appointment FindOrganizerAppointment(Appointment appointment) { try { Impersonate(appointment.Organizer.Address); var filter = new SearchFilter.IsEqualTo { PropertyDefinition = new ExtendedPropertyDefinition (DefaultExtendedPropertySet.Meeting, 0x03, MapiPropertyType.Binary), Value = GetObjectIdStringFromUid(appointment.ICalUid) }; var view = new ItemView(1) { PropertySet = new PropertySet(BasePropertySet.FirstClassProperties) }; return _service.FindItems(WellKnownFolderName.Calendar, filter, view).Items[0] as Appointment; } catch (Exception e) { throw e; } finally { DisableImpersonation(); } } /// <summary> /// Gets the object id string from uid. /// <remarks>The UID is formatted as a hex-string and the GlobalObjectId is displayed as a Base64 string.</remarks> /// </summary> /// <param name="id">The uid.</param> /// <returns></returns> private static string GetObjectIdStringFromUid(string id) { var buffer = new byte[id.Length / 2]; for (int i = 0; i < id.Length / 2; i++) { var hexValue = byte.Parse(id.Substring(i * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier); buffer[i] = hexValue; } return Convert.ToBase64String(buffer); } 
0
source

Note that the RequiredAttendees object will only be populated if it is a collection.

In the else statement add this check

 if(appointment.IsMeeting) { List<Attendee> remove = new List<Attendee>(); foreach (var attendee in appointment.RequiredAttendees) { if (IsResource(attendee.Address) && attendee.Address != resourceId) { remove.Add(attendee); } } remove.ForEach(a => appointment.RequiredAttendees.Remove(a)); if (!appointment.RequiredAttendees.Any(a => a.Address == resourceId)) { appointment.RequiredAttendees.Add(resourceId); } } 

meeting appointment information MSDN Link

+1
source

Source: https://habr.com/ru/post/1271819/


All Articles