Exchange webservice: Adding a contact 

Tags: .NET, Visual Studio, Exchange webservice

During the past 2 weeks or so I've been experimenting with the Exchange Webservice (in Exchange 2007 SP1).

I've been trying to create a contact in the contacts folder of a user (testuser). I came accross some problems while trying to accomplish this. Specifically when I tried to set properties that are actually used by Outlook (client properties) and which are not necessarily used by Exchange 2007. But you can still access and even create properties all you want. Lets kick this blog off with the basics of working with the ews (Exchange WebService).

Some ground work:

  • Create a new console app.
  • Add the Web Reference to your Exchange Webservice (eg.: http://myMailServer/ews/Exchange.Asmx) and lets name it ExchangeService.
  • Add the using to the ExchangeService

Now we can go and add a private member

private static ExchangeServiceBinding esb;

Initialize the ExchangeServiceBinding. You can insert credentials here in case of a https connection as seen in the example below.

esb = new ExchangeServiceBinding
{
   Credentials = new NetworkCredential
   {
      Domain = "example.com",
      UserName = "testUser",
      Password = "p455w0rd"
   },
   Url = https://192.168.2.143/EWS/Exchange.asmx
};
esb.RequestServerVersionValue = new RequestServerVersion();
esb.RequestServerVersionValue.Version = 
   ExchangeVersionType.Exchange2007_SP1;

As you can see in above code you need to set the server version, please do not ommit these 2 lines. If you do your code probably won't work. In some cases you will get an error like this: 

System.Web.Services.Protocols.SoapException: The request is valid but does not specify the correct server version in the RequestServerVersion SOAP header. Ensure that the RequestServerVersion SOAP header is set with the correct RequestServerVersionValue.

Now that we have the base of the application we can start concentrating on creating a contact, so we're going to create a method that does just that for us.

private static void CreateContact (string givenName, string surname)
{
  var contact = new ContactItemType();
  contact.GivenName = givenName;
  contact.Surname = surname;
  contact.DisplayName = contact.Subject = givenName + " " + surname;
  contact.EmailAddresses = new EmailAddressDictionaryEntryType[1];
  var email1 = new EmailAddressDictionaryEntryType();
  email1.Key = EmailAddressKeyType.EmailAddress1;
  email1.Value = "testUser@example.com";
  contact.EmailAddresses[0] = email1;
  var createItem = new CreateItemType();
  createItem.Items = new NonEmptyArrayOfAllItemsType
    {
       Items = new[] { contact }
    };
  var folder = new DistinguishedFolderIdType();
  folder.Id = DistinguishedFolderIdNameType.contacts;
  var targetFolder = new TargetFolderIdType();
  targetFolder.Item = folder;
  createItem.SavedItemFolderId = targetFolder;
  var response = esb.CreateItem(createItem);
}

You'll see the contact being created in you testUser's contacts folder.
If you don't fill out the DisplayName, the contact will complain about it in outlook when you open the contact and then close it without editing anything. Outlook will try to save the contact item although we did not change anything.

This was fairly easy to achieve, but just try to fill out all the contact's porperties you need. You'll soon find out that you need to use Extended Properties, because not all the properties are available on the ContactItemType type. I'll show you how to add 2 Extended Properties. Firstly the Gender of the contact and secondly the Title. Insert following somewhere before the instantiation of the CreateItemType createItem.

contact.ExtendedProperty =  new ExtendedPropertyType[2];
var gender = new ExtendedPropertyType();
gender.ExtendedFieldURI = new PathToExtendedFieldType();
gender.ExtendedFieldURI.PropertyTag = "0x3a4d";
gender.ExtendedFieldURI.PropertyType = MapiPropertyTypeType.Short;
gender.Item = "1";
var title = new ExtendedPropertyType();
title.ExtendedFieldURI = new PathToExtendedFieldType();
title.ExtendedFieldURI.PropertyTag = "0x3a45";
title.ExtendedFieldURI.PropertyType = MapiPropertyTypeType.String;
title.Item = "Dr.";
contact.ExtendedProperty[0] = gender;
contact.ExtendedProperty[1] = title;

As you can see both these Extended Properties have a PropertyTag. This is not always the case. In other properties you'll need to use the PropertyId and DistinguisedPropertyId, but we'll see samples of that in a later post in which I am going to discuss how you need to create a DistributionList with the contact created here as the only member.

The Property Tags and Ids can be found in the pdf's concerning the exchange protocol on MSDN or through a nice tool that helped me alot these past weeks: OutlookSpy.

That's it for now. I hope it was clear and helpfull in some way. If you have questions or remarks, do not hesitate to post a comment.

 
Posted by Wim De Coninck on 25-Sep-08
11 Comments  |  Trackback Url | Bookmark this post with:        
 
ab

Comments


Wes commented on Thursday, 4-Dec-2008
If my account has full access to Exchange, can I use this with my credentials to add a contact to another user's Contacts, without knowing the other user's password?


Wim De Coninck commented on Friday, 5-Dec-2008
Wes, I think you should take a look at http://msdn.microsoft.com/en-us/library/bb204095.aspx It has some info about Exchange Impersonation. It looks like it is possible however you'll need to add the following two Active Directory extended permissions in order to perform impersonation: - ms-Exch-EPI-Impersonation - ms-Exch-EPI-May-Impersonate As you can read in the link above. For the code part, before you process the createItem with the Exchange service binding (esb variable in the code above), you need to change the esb.Impersonation. esb.ExchangeImpersonation = new ExchangeImpersonation { ConnectingSID = new ConnectingSIDType { PrimarySmtpAddress = "testuser@example.com" } } Hope this helps.


Sean commented on Thursday, 8-Jan-2009
Thanks for the help. I'm getting the Save prompt from Outlook when opening and closing the contact without changing anything. I set the displayname property, but the Display As property seems to be the culprit. Any ideas? Thanks again.


Wim De Coninck commented on Friday, 9-Jan-2009
Sean, I stumbled across a simular problem. It is really hard for me to say what property or propertyvalue you are missing or what wasn't set correctly. Therefor I would suggest you first install the outlookspy application (it's a plug-in for outlook). With that installed you can select a contact in the address book (not open it) and click on the IMessage button of outlookspy. You'll now see a new window. Goto the Watch tab, click the 'all -->' button. Now move the screen a bit to the side or minimize it, open the contact you selected to watch and close it so the save is triggered. Select save and go back to the outlookspy window. You'll see all the properties that have been changed. Most of the properties that have been changed will be outlook specific properties. But there are probably a few you'll need to set when you upload the contact. If you have more questions, don't hesitate :)


venkat commented on Saturday, 10-Jan-2009
Hai I am working with exchange web service programming... let me know how to add... whether shall i install Microsoft exchange server 2007 to my system.. wat shall i give in the url, while adding reference.. I have fully confused... Let u please Suggest me...


Wim De Coninck commented on Saturday, 10-Jan-2009
Hi Venkat, The url for the reference you want to add should look like this: https://[your servername or server ip]/EWS/Exchange.asmx Make sure that you don't add a service reference, but add a webreference instead. You can do this by right clicking on your project file in the visual studio 2008 solution explorer and select add service reference. In the screen that just opened click the lower button on the left saying "Advanced". Next click on the button saying "add web reference" at nearly the same location. Then enter the url at the top and press the green arrow button. Next you'll probably be prompted for a login name and password. Use a username with enough rights like the administrator. So you wont hit your head on security issues. Then you should be able to start programming against the webservice. Hope this is an answer to your question. And have fun coding :)


Robert commented on Wednesday, 25-Feb-2009
Wim, Good stuff, there doesn't seem to be that much examples like this around on the net. I have a problem trying to translate this to VB (VS2008). I also tried the example available from MS to create contacts (http://msdn.microsoft.com/en-us/library/aa563318.aspx) and run into the same problem. It's probably my lack of knowledge of C#, any idea ? From the MS example I translated: createItemType.Items = new NonEmptyArrayOfAllItemsType(); createItemType.Items.Items = new ItemType[1]; to: createItemType.Items = New NonEmptyArrayOfAllItemsType() createItemType.Items.Items(1) = New ItemType() The second line throws an exception: System.NullReferenceException: Object reference not set to an instance of an object And another question: could you also use this routine to create contacts in the 'old' public folder store ? regards, Robert


Robert commented on Wednesday, 25-Feb-2009
The other problem I always have with the created contacts is that it does not seem to be recognized by Outlook correctly: although the email address is there, it is not underlined and the Display As field is empty. Only when you open and save the contact this is corrected, and only then you can use this contact in an Outlook created DL for example.


Wim De Coninck commented on Thursday, 26-Feb-2009
Robert, Let me start by addressing your second problem. I already answered a similar question two comment posts before your first, as a reply to Sean, please read that one first and let me know if that solved the issue. As for the first problem I would say there is indeed something wrong with the porting :). Since my VB is kinda rusty I'm not really sure. Try these lines: createItemType.Items = New NonEmptyArrayOfAllItemsType() createItemType.Items.Items = New ItemType(1) Now you should be able to add new ItemTypes to the Items collection As for the 'old' public folder store: if you can address it trough the Exchange webservice it should be the same routine except you'll need to specify the folder a bit differently. If you have any more questions, don't hesitate


Robert commented on Thursday, 26-Feb-2009
Wim, thanks. In the meantime I already managed to port the code to VB.Net and got it to work. FYI, the VB syntax is like: Dim arrayOfItems As New NonEmptyArrayOfAllItemsType() arrayOfItems.Items = New ItemType(1) {} arrayOfItems.Items(0) = contact The last issue is also already solved: I found that if you add an address to the contact (and perhaps a phonenumber) it is correctly recognized by Outlook On to the Distribution Lists, but will post on that subject :-)


Kapil Jadhav commented on Thursday, 20-May-2010
HI Wim De Coninck, I liked you article as there are very few articles on contacts in ex2007. I have a bit different scenario, I have to sync contacts from my DB to exchange and vice versa. I have managed it to do for mailbox as it was quite simple to just dump the mails from eachother, but for contacts I need to just sync new ones. Although, Enev if get to know how to read the contacts that would help me much. Thank you, Kapil

Your name  *
Email  *
Your URL 
Comment  *

Please enter the text from the image


Contact us - Raas Van Gaverestraat 83, 9000 Gent, Belgium - Tel. +32 (9) 330.15.00 - Privacy Statement - Sitemap - Sign In Developed with Microsoft Office SharePoint Server 2007