简体   繁体   中英

How do I (properly) inherit classes from EWS such as an Appointment?

Same problem as: https://stackoverflow.com/questions/11294207/exchange-web-services-argumentexception-using-my-own-contact-class

I am trying to write a derived class from Microsoft.Exchange.WebServices.Data.Appointment. However, the derived class cannot be saved without throwing what appears to be a serialization error. This happens even if I make no modifications to the derived class.

This works:

public void CreateTestAppointment() {
        Appointment appointment = new Appointment(Exchange) {
            ItemClass = "IPM.Appointment", //Exchange Specific. Dont touch unless you     know what this does. I sure as hell don't.
            Subject = string.Format("{0} Test", "Oliver")
        };
        appointment.RequiredAttendees.Add("okane@cottinghambutler.com");
        appointment.Body = new MessageBody {
            Text = "Meeting invite body text placeholder"
        };

        //Add item to the appropriate categories
        appointment.Categories.Add(string.Format("[C]{0}", "Arbitrary Client Group"));

        // Add calendar properties to the appointment.
        appointment.Start = DateTime.Now.AddMinutes(10);
        appointment.End = DateTime.Now.AddMinutes(30);

        appointment.Save(Hc360CallCalendarFolderId, SendInvitationsMode.SendOnlyToAll);
    }

But this doesn't:

 public void CreateTestAppointment() {
        InheritedAppointment appointment = new InheritedAppointment(Exchange) {
            ItemClass = "IPM.Appointment", //Exchange Specific. Dont touch unless you know what this does. I sure as hell don't.
            Subject = string.Format("{0} Test", "Oliver")
        };
        appointment.RequiredAttendees.Add("okane@cottinghambutler.com");
        appointment.Body = new MessageBody {
            Text = "Meeting invite body text placeholder"
        };

        //Add item to the appropriate categories
        appointment.Categories.Add(string.Format("[C]{0}", "Arbitrary Client Group"));

        // Add calendar properties to the appointment.
        appointment.Start = DateTime.Now.AddMinutes(10);
        appointment.End = DateTime.Now.AddMinutes(30);

        appointment.Save(Hc360CallCalendarFolderId, SendInvitationsMode.SendOnlyToAll);
    }

Which is very strange, as I'm not actually doing anything in the derived class.

    public class InheritedAppointment : Microsoft.Exchange.WebServices.Data.Appointment {
    public InheritedAppointment(ExchangeService serivce)
        : base(serivce) {

    }}

It looks like this is being seralized to XML, and some value is null, but I cannot for the life of me figure out what it is. Here's the raw error

Test Name: TestMeetingCreation Test FullName: Hc360LibTests.UnitTest1.TestMeetingCreation Test Source: c:\\Users\\okane\\Documents\\Visual Studio 2012\\Projects\\HealthCheck360OutlookCallScheduleHelper\\Hc360LibTests\\UnitTest1.cs : line 15 Test Outcome: Failed Test Duration: 0:00:00.5728502

Result Message: Test method Hc360LibTests.UnitTest1.TestMeetingCreation threw exception: System.ArgumentException: The empty string '' is not a valid local name. Result StackTrace: at System.Xml.XmlWellFormedWriter.WriteStartElement(String prefix, String localName, String ns) at Microsoft.Exchange.WebServices.Data.EwsServiceXmlWriter.WriteStartElement(XmlNamespace xmlNamespace, String localName) at Microsoft.Exchange.WebServices.Data.PropertyBag.WriteToXml(EwsServiceXmlWriter writer) at Microsoft.Exchange.WebServices.Data.CreateRequest 2.WriteElementsToXml(EwsServiceXmlWriter writer) at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.WriteBodyToXml(EwsServiceXmlWriter writer) at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.WriteToXml(EwsServiceXmlWriter writer) at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.EmitRequest(IEwsHttpWebRequest request) at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.BuildEwsHttpWebRequest() at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ValidateAndEmitRequest(IEwsHttpWebRequest& request) at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest 1.Execute() at Microsoft.Exchange.WebServices.Data.ExchangeService.InternalCreateItems(IEnumerable 1 items, FolderId parentFolderId, Nullable 1 messageDisposition, Nullable 1 sendInvitationsMode, ServiceErrorHandling errorHandling)
at Microsoft.Exchange.WebServices.Data.Item.InternalCreate(FolderId parentFolderId, Nullable
1 sendInvitationsMode, ServiceErrorHandling errorHandling)
at Microsoft.Exchange.WebServices.Data.Item.InternalCreate(FolderId parentFolderId, Nullable
1 sendInvitationsMode, ServiceErrorHandling errorHandling)
at Microsoft.Exchange.WebServices.Data.Item.InternalCreate(FolderId parentFolderId, Nullable
1 messageDisposition, Nullable`1 sendInvitationsMode) at Microsoft.Exchange.WebServices.Data.Appointment.Save(FolderId destinationFolderId, SendInvitationsMode sendInvitationsMode) at HealthCheck360ExchangeLib.CallSlotRepository.CreateTestAppointment() in c:\\Users\\okane\\Documents\\Visual Studio 2012\\Projects\\HealthCheck360OutlookCallScheduleHelper\\HealthCheck360ExchangeLib\\CallSlotRepository.cs:line 70 at Hc360LibTests.UnitTest1.TestMeetingCreation() in c:\\Users\\okane\\Documents\\Visual Studio 2012\\Projects\\HealthCheck360OutlookCallScheduleHelper\\Hc360LibTests\\UnitTest1.cs:line 17

It seems that it is not possible to save an inherited item.

If you look deep enough in the code for the EWS Managed API you will find that the serialization determines the element names in the XML from either the ServiceObjectDefinitionAttribute or from the method ServiceObject.GetXmlElementNameOverride. The Appointment class inherits from Item which in turn inherits from ServiceObject. The Appointment class also has the ServiceObjectDefinitionAttribute and is serialized with the XML element name "CalendarItem".

So, to use a class inherited from Appointment you need to either use the ServiceObjectDefintionAttribute on your class or you have to override GetXmlElementNameOverride. Unfortunately ServiceObjectDefintionAttribute and GetXmlElementNameOverride are internal so there is no way to do this.

The question is why do you want to use an inherited class? Did you expect Exchange to be able to save the properties on your class? In that case you might want to take a look at ExtendedProperties .

UPDATE:

If you want to expose the extended properties as real properties on your own class you can do it by delegating to an Appointment object. It is not perfect but it is an option:

public class ExtendedAppointment
{
    Appointment _appointment;

    public ExtendedAppointment(Appointment appointment)
    {
        _appointment = appointment;
    }

    public Appointment Appointment { get { return _appointment; } }

    public object SomeExtendedProperty
    {
        get 
        { 
            return _appointment.ExtendedProperties[0].Value;
        }

        set
        {
            _appointment.ExtendedProperties[0].Value = value;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM