Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating a Contact with EWS

I have struggled to find out how to work with EWS and have managed to work out how to do just about everything I've wanted to. I am using EWS to manage contacts between a custom database and the Exchange server (2007). Adding and deleting works just fine, but I cannot update a contact. To workaround this, I deleted the contact and recreated it, but the problem comes in when the contact is edited via Outlook (or whatever else).

I tried to follow what this link says:

http://msdn.microsoft.com/en-us/library/exchange/ee693002(v=exchg.80).aspx

but I get an error saying that only one property can be updated. Then I update each property one at a time, and as soon as I try to update a phone number I get an error which says: "The element 'Updates' in namespace 'http://schemas.microsoft.com/exchange/services/2006/types' has incomplete content."

Here is the code, basically:

ItemId itemId = contactToUpdate.Id;
Contact updateContact = Contact.Bind(service, itemId);
updateContact.PhoneNumbers[PhoneNumberKey.HomePhone] = customContact.HomeTelephone;
updateContact.Update(ConflictResolutionMode.AlwaysOverwrite);

Does anyone know why I get this error? Can anyone answer how to actually update an item? Is there documentation I have missed?

The version of the EWS dll's is 15.0.516.12.

like image 940
Marc K Avatar asked Jan 15 '23 23:01

Marc K


1 Answers

I found the answer to this after much debugging. I'm not going to explore more to find out why, but you can't do this:

updateContact = Contact.Bind(service, itemId);
updateContact.PhoneNumbers[PhoneNumberKey.HomePhone] = customContact.HomePhone;
updateContact.PhoneNumbers[PhoneNumberKey.MobilePhone] = customContact.MobilePhone;
updateContact.PhoneNumbers[PhoneNumberKey.BusinessPhone] = customContact.BusinessPhone;
updateContact.Update(ConflictResolutionMode.AlwaysOverwrite);

You can, however, set only one phone number and then change the values for the other two while debugging (while on a break point). Weird.

Anyway, there is a problem - you can't update one of these dictionary values if the value does not change (that's the answer in short), so do a check first to see if the value changed. Next, if a value is an empty string, you need to rather save it as null. You also need to check whether the dictionary entry exists before trying to read its value.

string number;
bool numberFound;

numberFound = updateContact.PhoneNumbers.TryGetValue(PhoneNumberKey.HomePhone, out number);
if ((numberFound && number != customContact.HomePhone) ||
    (!numberFound && !string.IsNullOrEmpty(customContact.HomePhone)))
{
    updateContact = Contact.Bind(service, itemId);
    updateContact.PhoneNumbers[PhoneNumberKey.HomePhone] = customContact.HomePhone == "" ? null : customContact.HomePhone;
    updateContact.Update(ConflictResolutionMode.AlwaysOverwrite);
}

To update an address:

updateContact = Contact.Bind(service, itemId);
updateContact.PhysicalAddresses[PhysicalAddressKey.Home].Street = customContact.Street == "" ? null : customContact.Street;
updateContact.PhysicalAddresses[PhysicalAddressKey.Home].State = customContact.Suburb == "" ? null : customContact.Suburb;
updateContact.PhysicalAddresses[PhysicalAddressKey.Home].City = customContact.City == "" ? null : customContact.City;
updateContact.PhysicalAddresses[PhysicalAddressKey.Home].CountryOrRegion = customContact.Country == "" ? null : customContact.Country;
updateContact.PhysicalAddresses[PhysicalAddressKey.Home].PostalCode = customContact.AreaCode == "" ? null : customContact.AreaCode;
updateContact.Update(ConflictResolutionMode.AlwaysOverwrite);

This, in my opinion, is sloppy implementation of the API (and poor documentation).

The fact that an update needs to be performed for each property of an item could possibly be due to the server running Exchange 2007, but this has yet to be confirmed.

I tried with both version 14 and 15 of Microsoft.Exchange.WebServices with the same results.

Update

But wait, there's more.

I'm posting a lot of code to illustrate how to update different phone numbers, addresses, etc. The code also shows how to update (or set) title, gender, suffix and a custom property (user defined field - which if you want to appear in Outlook, you need to add the user defined field to the contacts folder).

Here is a complete, working piece of code:

Contact updateContact = Contact.Bind(service, itemId);
updateContact.GivenName = customContact.Name;
updateContact.Surname = customContact.Surname;

EmailAddress emailAddress;
bool emailAddressFound;

emailAddressFound = updateContact.EmailAddresses.TryGetValue(EmailAddressKey.EmailAddress1, out emailAddress);
if (emailAddressFound && emailAddress.Address != customContact.Email)
{
    emailAddress.Address = customContact.Email == "" ? null : customContact.Email;
}
else if (!emailAddressFound && !string.IsNullOrEmpty(customContact.Email))
{
    updateContact.EmailAddresses[EmailAddressKey.EmailAddress1] = customContact.Email;
}
updateContact.Initials = customContact.Initials;

string number;
bool numberFound;

numberFound = updateContact.PhoneNumbers.TryGetValue(PhoneNumberKey.HomePhone, out number);
if ((numberFound && number != customContact.HomePhone) || (!numberFound && !string.IsNullOrEmpty(customContact.HomePhone)))
{
    updateContact.PhoneNumbers[PhoneNumberKey.HomePhone] = customContact.HomePhone == "" ? null : customContact.HomePhone;
}
numberFound = updateContact.PhoneNumbers.TryGetValue(PhoneNumberKey.MobilePhone, out number);
if ((numberFound && number != customContact.CellPhone) || (!numberFound && !string.IsNullOrEmpty(customContact.CellPhone)))
{
    updateContact.PhoneNumbers[PhoneNumberKey.MobilePhone] = customContact.CellPhone == "" ? null : customContact.CellPhone;
}
numberFound = updateContact.PhoneNumbers.TryGetValue(PhoneNumberKey.BusinessPhone, out number);
if ((numberFound && number != customContact.WorkPhone) || (!numberFound && !string.IsNullOrEmpty(customContact.WorkPhone)))
{
    updateContact.PhoneNumbers[PhoneNumberKey.BusinessPhone] = customContact.WorkPhone == "" ? null : customContact.WorkPhone;
}

PhysicalAddressEntry phsicalAddress;
bool phsicalAddressFound;
int phsicalAddressLength = (customContact.Street + customContact.Suburb + customContact.City + customContact.Country + customContact.AreaCode).Length;
phsicalAddressFound = updateContact.PhysicalAddresses.TryGetValue(PhysicalAddressKey.Home, out phsicalAddress);
if (phsicalAddressFound)
{
    updateContact.PhysicalAddresses[PhysicalAddressKey.Home].Street = customContact.Street == "" ? null : customContact.Street;
    updateContact.PhysicalAddresses[PhysicalAddressKey.Home].State = customContact.Suburb == "" ? null : customContact.Suburb;
    updateContact.PhysicalAddresses[PhysicalAddressKey.Home].City = customContact.City == "" ? null : customContact.City;
    updateContact.PhysicalAddresses[PhysicalAddressKey.Home].CountryOrRegion = customContact.Country == "" ? null : customContact.Country;
    updateContact.PhysicalAddresses[PhysicalAddressKey.Home].PostalCode = customContact.AreaCode == "" ? null : customContact.AreaCode;
}
else if (!phsicalAddressFound && phsicalAddressLength > 0)
{
    updateContact.PhysicalAddresses[PhysicalAddressKey.Home] = homeAddress;
}
phsicalAddressLength = (customContact.BusinessStreet + customContact.BusinessSuburb + customContact.BusinessCity + customContact.BusinessCountry + customContact.BusinessAreaCode).Length;
phsicalAddressFound = updateContact.PhysicalAddresses.TryGetValue(PhysicalAddressKey.Business, out phsicalAddress);
if (phsicalAddressFound)
{
    updateContact.PhysicalAddresses[PhysicalAddressKey.Business].Street = customContact.BusinessStreet == "" ? null : customContact.BusinessStreet;
    updateContact.PhysicalAddresses[PhysicalAddressKey.Business].State = customContact.BusinessSuburb == "" ? null : customContact.BusinessSuburb;
    updateContact.PhysicalAddresses[PhysicalAddressKey.Business].City = customContact.BusinessCity == "" ? null : customContact.BusinessCity;
    updateContact.PhysicalAddresses[PhysicalAddressKey.Business].CountryOrRegion = customContact.BusinessCountry == "" ? null : customContact.BusinessCountry;
    updateContact.PhysicalAddresses[PhysicalAddressKey.Business].PostalCode = customContact.BusinessAreaCode == "" ? null : customContact.BusinessAreaCode;
}
else if (!phsicalAddressFound && phsicalAddressLength > 0)
{
    updateContact.PhysicalAddresses[PhysicalAddressKey.Business] = businessAddress;
}
updateContact.Birthday = customContact.Birthdate;
updateContact.WeddingAnniversary = customContact.MaritalStatusDate;
// Extended properties -------------------------------------------------------------
ExtendedPropertyDefinition extendedPropertyDefinition;
// Gender
if (!string.IsNullOrEmpty(customContact.Gender))
{
    extendedPropertyDefinition = new ExtendedPropertyDefinition(0x3a4d, MapiPropertyType.Short);
    switch (customContact.Gender)
    {
        case "Male":
            updateContact.SetExtendedProperty(extendedPropertyDefinition, 2);
            break;
        case "Female":
            updateContact.SetExtendedProperty(extendedPropertyDefinition, 1);
            break;
        default:
            updateContact.SetExtendedProperty(extendedPropertyDefinition, 3);
            break;
    }
}
// Title
if (!string.IsNullOrEmpty(customContact.Title))
{
    extendedPropertyDefinition = new ExtendedPropertyDefinition(0x3a45, MapiPropertyType.String);
    updateContact.SetExtendedProperty(extendedPropertyDefinition, customContact.Title);
}
// Suffix
if (!string.IsNullOrEmpty(customContact.Suffix))
{
    extendedPropertyDefinition = new ExtendedPropertyDefinition(0x3a05, MapiPropertyType.String);
    updateContact.SetExtendedProperty(extendedPropertyDefinition, customContact.Suffix);
}
// Custom property
extendedPropertyDefinition = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "customProperty", MapiPropertyType.String);
updateContact.SetExtendedProperty(extendedPropertyDefinition, customContact.CustomProperty);
// File the contact
updateContact.Subject = customContact.Name + " " + customContact.Surname;
updateContact.DisplayName = customContact.Name + " " + customContact.Surname;
updateContact.Update(ConflictResolutionMode.AlwaysOverwrite);
like image 67
Marc K Avatar answered Mar 27 '23 18:03

Marc K