在EWS 1.1中,更新约会将使其变为会议



我要做的是:

  • 获取用户日历上两个日期之间的所有项目
  • 更新LocationSubject

我得到的项目与:

FindItemsResults<Appointment> findResults = calendar.FindAppointments(new CalendarView(startDate, endDate));

这个查询工作正常。但是每当我调用Update来保存项目时,我都会得到一个异常:

Microsoft.Exchange.WebServices.Data.ServiceResponseException: One or more recipients are invalid.

即使我得到一个异常,该项目被保存并被更改为将IsMeeting设置为true!现在更新的项目是与组织者的会议等等……对我来说,这实际上是数据损坏。

下面是代码。没有比这更复杂的了。我已经通过更改LocationSubject进行了测试,两者都会导致问题。

Appointment a = Appointment.Bind(_service, new ItemId(id));
a.Location = newLocation
a.Update(ConflictResolutionMode.AlwaysOverwrite);

我错过了什么概念还是什么?这似乎是一个相当严重的问题。

哎呀,这是EWS 1.1针对Office 365服务器

我从这个问题中找到了答案:

Exchange Appointment Types

关键是Update方法需要在第二个参数中设置SendInvitationsOrCancellationsMode.SendToNone标志时调用。

:

a.Update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToNone);

所以,当您永远不想向其他与会者发送约会更新时,tig的答案就有效了。然而,要正确回答这个问题,实际上需要加载与会者状态。

默认情况下,它正在尝试向与会者发送约会更新,但是您的约会对象没有加载与会者状态,因此爆炸。当您执行绑定时,您应该加载与会者属性。您可能还应该加载组织者,以覆盖另一种边缘情况:

  • AppointmentSchema。RequiredAttendees
  • AppointmentSchema。OptionalAttendees
  • AppointmentSchema。资源
  • AppointmentSchema。组织者

如果你想做一个向与会者发送更新的更新,这将使与会者填充。

然而,还有另一个你需要担心的边缘情况。如果您的约会没有添加与会者(只有组织者),那么EWS可能仍然会抱怨并抛出此错误。在某些州,它实际上对约会有效,但在其他州则失败。

所以最完整的解决方案是:

  1. 加载与会者状态。
  2. 检查与会者状态,以查看除组织者之外是否还有其他与会者(取决于创建约会的方式,组织者可能出现也可能不出现在RequiredAttendees集合中)。如果没有,那么你必须使用sendinvitationsorcancellationmode . sendtonone。

所以完整的样本看起来像这样:

Appointment a = Appointment.Bind(_service, new ItemId(id), new PropertySet(AppointmentSchema.RequiredAttendees, AppointmentSchema.OptionalAttendees, AppointmentSchema.Resources, AppointmentSchema.Organizer));
a.Location = newLocation
// Check if the appointment has attendees other than the organizer. The organizer may
// or may not appear in the required attendees list.
if (HasNoOtherAttendee(a.Organizer.Address, a.RequiredAttendees) &&
    (a.OptionalAttendees.Count == 0) && (a.Resources.Count == 0))
{
    a.Update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToNone);
}
else
{
    // We have other attendees in the appointment, so we can use SendToAllAndSaveCopy so
    // they will see the update.
    a.Update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToAllAndSaveCopy);
}

bool HasNoOtherAttendee(string email, AttendeeCollection attendees)
{
    bool emptyOrOnlyMe = true;
    foreach (var a in attendees)
    {
        if (!string.Equals(email, a.Address, StringComparison.OrdinalIgnoreCase))
        {
            emptyOrOnlyMe = false;
            break;
        }
    }
    return emptyOrOnlyMe;
}

要回答这个问题

"即使我得到一个异常,项目被保存并被更改为把IsMeeting设为true!现在更新的项目是一个会议组织者等等……对我来说,这实际上是数据损坏。"

微软文档中以小字说明:"会议请求只是一个有与会者的约会。您可以通过向约会"添加必需的与会者、可选的与会者或资源来将约会转换为会议请求,如下所示http://msdn.microsoft.com/en-us/library/office/dd633641%28v=exchg.80%29.aspx

换句话说,只要您有任何与会者,Exchange将自动将其转换为会议。

public static bool UpdateAppointment(ExchangeCredential credentials,
           ItemId appointmentId, string newLocation, string newSubject, 
DateTime startTime,
            DateTime endTime)
        {
            ExchangeService service = GetExchangeService(credentials);
            try
            {
                Appointment appt = Appointment.Bind(service, appointmentId,
                    new PropertySet(BasePropertySet.IdOnly, AppointmentSchema.Start,
                        AppointmentSchema.ReminderDueBy, AppointmentSchema.End,   AppointmentSchema.StartTimeZone,
                        AppointmentSchema.TimeZone));
                appt.Location = newLocation;
                appt.Start = startTime;
                appt.End = endTime;
                appt.Subject = newSubject;
                // very important! you must load the new timeZone
                appt.StartTimeZone = TimeZoneInfo.Local;
                //appt.Body.Text = newBody; //if needed
                appt.Update(ConflictResolutionMode.AlwaysOverwrite);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return true;
        }

最新更新