OutlookContactProvider


Back in May, I wrote an article for the Office Developer Center on MSDN on an idea I had for creating Outlook Calendar Providers (and later demonstrated how to write an additional provider for this to allow Windows XP Media Center 2004 recording schedules to be viewed as calendars in Outlook, which reminds me that I need to update that code for Media Center 2005). Since then, I’ve received several requests for code to do the same with contacts and contact lists instead of with events and event lists.


As it’s the holiday season, I decided to spend a few minutes granting those requests and creating a version of the calendar providers code that instead works with contacts.  For anyone who’s interested, I’d suggest reading the article about calendar providers first, as the contacts code is very similar.  The source for the new project is then available here. Included in the source is an example provider that connects to a SQL Server and provides a contact list for the customers in the Northwind database. 

Of course, you can write your own providers to access whatever data source is of most interest to you.

Happy Holidays!


Stephen


 

OutlookContactProvider.zip

Comments (53)

  1. Thanx again Stephen,

    I already used your OutlookCalendarProvider code to create calendars for the movies in the local theater and the current series and movies on TV (through XMLTV).

    The OutlookContactProvider will come in handy sometime for sure…

  2. Curt Hagenlocher says:

    Awesome!

    Do you have any pointers to this SharePoint API? Could the same API be used to write an updater for the Northwind database? I’d be happy to write and share some sample code, but I haven’t been able to find any specs.

  3. Dror says:

    wonderfull !

    Thank you

    Happy Chrismes!

    Dror Engel

  4. Stephen Toub says:

    Curt-

    This solution implements a Web service that has the same contract as the SharePoint Lists.asmx Web service, which is documented in the WSS docs, and then just points Outlook at that Web service instead of at the one in a SharePoint site. While the WSS Web service does support read/write, the Outlook client that consumes this service only supports reading, at least in the current version. So, for now, unless you were to write your own plug-in for Outlook to consume the Web service (which this solution avoids doing), you’re not going to be able to update the data source from Outlook. As such, my provider implementation only supports the providing of information, not of the updating of it. If a future version of Outlook supports two-way synchronization with SharePoint, I’ll see about updating both of these samples to allow for updating, as well.

    Happy holidays,

    Stephen

  5. Curt Hagenlocher says:

    Got it. Thanks.

  6. Fun with Toub’s Custom Calendar Providers

  7. Great to have the Contact provider sample. As additional background, also take a look at Randy Byrne’s "What’s New in Microsoft Office Outlook 2003 for Developer’s" article @ http://msdn.microsoft.com/library/?url=/library/en-us/odc_ol2003_ta/html/odc_OLWhatsNew2k3.asp is also a good reference for Outlook 2003 and SharePoint integration.

    The title is misleading as the article spends quite a bit of time talking specifically about a COM Add-In approach for doing SharePoint contact integration.

    Thanks again Stephen,

    Michael.

  8. Eivind says:

    I tried to open the project in Visual Studio 2005 and did get some ambiguous references and naming conflicts when the project was converted (without errors). Any quick fix?

  9. Make sure you’re opening it in 2005 as a Web site hosted on the file system, browsing to the OutlookContactProvider folder. I did that and it compiled without warning or error. Note that there may still be some fixups necessary in the web.config and whatnot, in terms of specifying where the various providers live and whatnot.

  10. Ahmad says:

    Great!

    Is there a way to create distribution lists automatically with this?

  11. Pete says:

    any tips for the OutlookCalendarProvider on getting formating to display in the description (i.e. rtf or html)?

    Also a source for other appointment ows_ fields to the appointment form field

    (i.e. ows_title => Subject, ows_EventDate=> Start time etc) as I would like to set the Label and Categories

  12. jba-mono says:

    This project seems to make what I want to do, too easy. So the question remains how scalable is this. Does it do a full system lookup everytime a user opens the folder in outlook or is it cached inteligently by outlook?

    We have a system with 45000 active personell in it at any one time, and while I would like to expose them all as public folder, I’m wondering what the performance consequences of this will be.

  13. Brandon says:

    Hi jba-mono,

    We had a similar concern as well.  The solution for us was to store the contacts in a static variable and only query our server once a day.  We also deployed a group policy to make the outlook clients sync only once a day as well.  It works for us…

    -Brandon

  14. JM says:

    I’m having trouble getting this to work.

    I created and installed the code in a virtual directory from the site root with framework 1.1, i can click on "View Events" an view all the contacts listed, i can click on "Link to Outlook" and after confirmation the folder appears on outlook but it never import the contacts. Outlook always give an error…

    Task ‘SharePoint’ reported error (0x8000FFFF) : ‘An error occurred either in Outlook or Windows SharePoint Services. Contact the Windows SharePoint Services site administrator.’

    Does anyone has the same problem?

  15. Matt Brailsford says:

    Anyone else had problems with this in .NET 2, i keep getting the following error when i click on the link to add it to outlook.

    "Outlook cannot add the requested Windows SharePoint Services folder"

  16. Brandon says:

    Hi Matt,  

    I think I got that message when I didn’t have the service installed in a virtual directory called OutlookContactProvider…  Also… If you are trying to copy the link an make a shortcut to the location I also ran into a problem where the last part of the URL was cut off because it was too long.  This happened when I tried to make an email with the hyperlink in Outlook and also when I tried to make a shortcut to it manually.

    Just an idea…

    -Brandon  

  17. Matt Brailsford says:

    Brandon  

    You were right, running it from a virtual directory called OutlookContactProvider worked.

    Anyone know of any reasons why it works this way?

    PS Thanks Brandon, this was doing my tree in yesterday, spent all day on it to no avail, you have saved my sanity =D

  18. Matt Brailsford says:

    Hi Guys,

    I seem to have run into a problem, though i’m not sure if it’s the contact provider or something else, but we have been using the contact provider to be able to show act contacts in outlook. It’s been working great, but for one guy when he sends emails, in the sent email folder it shows that he sent it to a different person. When he looks at it in closer detail the email adress is the corect one, but it is showing the wrond name.

    Has anybody else come across this, either with the contactprovider or outlook in general?

    Any help greatly apprechiated.

  19. Matt Brailsford says:

    Hey,

    I’m not sure if this is true or not, but i think the way that the "ow_ID" is set is causing problems in outlook.

    At the moment you set the id with a counter whilst looping through a contact collection. However, when a new person is added, the id’s beyond that contact move on one.

    Now the problem i was having was when an email was sent, outlook would say that you had sent the email to the contact in front of the one you actually sent it to.

    Anyway, i have added a contactid property to the contact object (which is unique to each contact) and am using that instead.

    Seems to work so far, you just have to remember to return the list in contactid order assending.

    Does this ring true with anybody else?

    Many thanks

    Matt

  20. Elena Nakhmanson says:

    JM,

    Did you (or anyone else) ever found the cause of  error (0x8000FFFF)? I am having the same problem when trying to connect a sharepoint contact list to Outlook. I am running MOSS 2007 Beta2 TR and Outlook Beta2 TR.

    Many thanks,

    Elena.

  21. Stephen Toub says:

    I’ve received several emails from folks who have been successfully using my Outlook Calendar Provider

  22. Peter says:

    I am trying to make my own contact list for outlook 2007 by simulating a sharepoint contact list, but the example code does not work as it is, and I do not understand how to change it.

    Here is some code for the calendar based on your code, and it has added some "Fields" elements you did not use:

    http://blogs.msdn.com/pcreehan/archive/2006/11/21/custom-calendar-providers-for-outlook-2007.aspx

    But I do not understand from where this knowledge about "Fields" comes from.

    I mean, where is it documented, or (if it is not documented) how can I see what kind of data a normal sharepoint list is sending to outlook ?

  23. I don’t believe it’s documented anywhere.  You can use a network sniffer or a debugging HTTP proxy to watch the traffic between Outlook and SharePoint in order to discover what fields are sent back and forth.

  24. Norman says:

    I too am frustrated by not being able to find any documentation on what fields Outlook will look for in the response from the web service calls.

    I addition to the ones in your sample the following seem to work

    ows_HomeAddress

    ows_HomeCity

    ows_HomeState

    ows_HomeZip

    ows_HomeCountry

    but these dont

    ows_OtherAddress

    ows_OtherCity

    ows_OtherState

    ows_OtherZip

    ows_OtherCountry

    I would really like to be able to pull through the Email2 and Email3 contact fields as well as the categories.

    Has anyone had any luck with any other fields?

  25. John says:

    I had the annoying error from sharepoint using Outlook 2007, Vista and my fake WSS service deployed on my local IIS7 instance.  After tweaking with it for a while, I decided to do this

    1)  Create an application which connected to a sharepoint service and retrieved a list and also connected to MY service and retrieved a list

    2)  Compare the "GetList" XmlNode which was returned by both services

    I noticed that the XmlNode that was returned by the code provided above is VERY short compared to the XmlNode which was provided by SharePoint.  I’m not sure what parts MUST be there and what parts are just extra fluff.

    It is a total hack, but I got rid of the error by returning the XML Node that SharePoint would have returned, just replacing a few values with my list name, ID, etc. and it worked first time.

    I also noticed that the XmlNode returned by the SharePoint site includes all of the fields which are available to display.  This might assist you guys in seeing what information you can pass.

  26. NamSin says:

    Anyone getting this error:

    Task ‘SharePoint’ reported error (0x8000FFFF) : ‘An error occurred either in Outlook or Windows SharePoint Services. Contact the Windows SharePoint Services site administrator.’

    I think I found The solution – You need a active network connection for some reason. If all network adapters are "disconnected" I get that error

    HTH

  27. andew says:

    how do i get the code to add an e-mail address?

    thanks

  28. Luis says:

    Hello:

    I am getting this error too:

    Task ‘SharePoint’ reported error (0x8000FFFF) : ‘An error occurred either in Outlook or Windows SharePoint Services. Contact the Windows SharePoint Services site administrator.’

    We run MOSS 2007 and I run Office 2007.

    Any ideas on how to fix this problem? We cannot get people to sync tasks.

  29. nilslahr says:

    I also get:

    Task ‘SharePoint’ reported error (0x8000FFFF) : ‘An error occurred either in Outlook or Windows SharePoint Services. Contact the Windows SharePoint Services site administrator.’

    I’m running Office 2007 and Exchange 2007.  When I view the events for the list the contacts show up as expected.  

  30. Micheal Howard says:

    Error Fixed,

    Remove the SharePoint lists under account settings. One of the SharePoint sites are down and outlook is not able to successfully connect to the SharePoint Server.

  31. Greg Palmes says:

    Found a workaround on following URL…

    http://www.tabletquestions.com/microsoft-office/34683-errors-syncing-sharepoint-2007-lists-outlook-2007-a.html

    NET STOP SENS

    run that, fixed for me also on VPC test environment

  32. This is wonderful.  I can view the contacts using the Outlook Contact panel…but when I am in EMail and select to create a new email, I can not see any contacts listed for this provider.  Am I doing something wrong?

  33. Jack Brinegar says:

    Disregard my last…simple oversight that the Northwind database was missing the EMAIL field.

  34. Darren says:

    Does this solution bring across the groups as well as contacts?

  35. Neil says:

    Has anyone managed to get around the read-only outlook 2003 limitation? I’m stuck working with a Office 2003 and want to provide calandaring via outlook to my web app.

    I imagine diving into VSTO is the only way out, but if anyone can point me at an addin examples that allow write access to SP list that would be grand.

  36. Andi says:

    I changed NorthwindContactProvider.cs to connect to a mysql database. But it still tries to connect to SQL-Server. Must i recreate the dll-file? How can this be done without Visual Stuido?

  37. Wilson says:

    Hi,

    I am trying to convert the ContactProvider code into VB.net 2.0, and I am getting the "Task… Reported error (0x80004005) the windows sharepoint services folder could not be found…….."

    any ideas what I have missed here?  

    also that GUID for the NorthwindProvider, is that a system genearted ID or I can just randomly assign a new set of GUID for my new provider?

    by the way I am running XP and office 2003.  

    Many thanks,

  38. Wilson says:

    Hi,

    got the web service running fine now..

    but I have problem getting the Category field working for the contact.

    AddAttribute(node, Nothing, "ows_Category", Nothing, "Business")

    AddAttribute(node, Nothing, "ows_Categories", Nothing, "Business")

    but both doesn’t seems to work..  does anyone know what is the correct name for the Category ows_ field for sharepoint?

    thanks.

  39. Sam says:

    Hi Guys, I have finally managed to get Stephen Toub code "Custom Calendar Providers for Outlook 2003" to work but I have one doubt, which I need your help for. I need to be able delete an event from Outlook calendar when an event from my custom calendar is deleted. Does anyone know how to do that. Please this is very urgent…

    If anyone knows how to do this then please do let me know…

    I’ll be looking forward for your replies….

    Thanks in advance,

    Sam

  40. Sean Cantellay says:

    Synchronizing a SharePoint Calendar with Outlook has been a problem not just for us, but for others as well. We have been connecting the calendars the recommended way Actions->Connect to Outlook. The calendar gets added and populated the first time but subsequent changes that are made to the SharePoint calendar are not updated to the Outlook calendar. When running a SendReceive the following error is given:

    Task ‘SharePoint’ reported error (0×8000FFFF) : ‘An error occurred either in

    Outlook or SharePoint. Contact the SharePoint site administrator.’

    I have check and rechecked the settings in both SharePoint and Outlook, nothing that I did seamed to fix the issue. So I opened a SharePoint site that I had installed on my local machine and connected the calendar from that site to my Outlook and was able to receive updated with no error. The only piece that was not the same in the two instances was that Exchange was out of the picture. After talking with a coworker we realized that a client of ours started seeing the same issues after doing a migration to Exchange 2007.

    I am not a Exchange guy so I will be meeting with one of our network engineers to see what we can find.

    Sean Cantellay

  41. J Nigon says:

    Great code – this is exactly what I’ve been looking for.  I finally have this running in Outlook 2007 on .net 1.1.  

    Has anyone managed to get this working in .net 2.0 or 3.5, or perhaps VB?    Can you share your project?  azzurij [at] hotmail

    Thanks!

  42. Hello All,

    The solution worked for me for the Task ‘SharePoint’ reported error (0x8000FFFF):

    There is a .Net passport that stores usernames and passwords. It’s located in the "Control PanelUser AccountsUser AccountsManage your network passwords" for Vista and "Control PanelUser AccountsYour username Change My .Net Password"

    If you change your password in Workspace and you have chosen to sign in automaticaly this error occurs, because the stored password is different.

    Hope this helps.

    Regards,

    Alexander Alexandrov

  43. Plamen says:

    @Alexander Alexandrov

    Thank you, Alexander, for the effort to put it up here. Finally, there is a simple exlanation to this problem. It took me two nights until I found your post.

  44. jr says:

    Is the code for this posting still available?

  45. Yup, as an attachment to the post. I’ve also updated the link in the post.

  46. Paul LInton says:

    I tried to run the code but have been getting the same 8000ffff error that many people report.  When I look at WssListResponse.GetListDescription it doesn’t add the <

    Fields> element to the doc.  When I add that everything starts to work.

    So, is the code in the download the right version?

  47. Dimitry says:

    Hi PAul Linton, could you be more specific on where you added the <Fields> .. ? point me to a new version of the code please?

  48. Paul Linton says:

    I haven’t posted the code anywhere.  In the downloaded code the end of WSSListResponse.GetListDescription has

    <<<snip

    AddAttribute(list, null, "ShowUser", null, "TRUE");

    // Return the XML

    return doc;

    <<<unsnip

    In my code I have (no guarantees that this will work for you as I have also attempted to merge the Contact and Calendar code in to one project)

    <<< snip

    AddAttribute(list, null, "ShowUser", null, "TRUE");

    //Create Fields node

    XmlElement fieldsNode = doc.CreateElement(null, "Fields", _wssns);

    list.AppendChild(fieldsNode);

    XmlElement tmpEl;

    //Append Fields

    tmpEl = AddFieldElement(doc, fieldsNode, "Counter", "tp_ID", "ID", "ID", true, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "nvarchar1", "Title", "Title", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "DateTime", "tp_Modified", "Modified", "Modified", true, false, true);

    AddAttribute(tmpEl, null, "StorageTZ", null, "TRUE");

    tmpEl = AddFieldElement(doc, fieldsNode, "DateTime", "tp_Created", "Created", "Created", true, false, true);

    AddAttribute(tmpEl, null, "StorageTZ", null, "TRUE");

    tmpEl = AddFieldElement(doc, fieldsNode, "User", "tp_Author", "Author", "Created By", true, false, true);

    AddAttribute(tmpEl, null, "List", null, "UserInfo");

    tmpEl = AddFieldElement(doc, fieldsNode, "User", "tp_Editor", "Editor", "Modified By", true, false, true);

    AddAttribute(tmpEl, null, "List", null, "UserInfo");

    tmpEl = AddFieldElement(doc, fieldsNode, "Integer", "tp_Version", "owshiddenversion", "owshiddenversion", true, true, true);

    AddAttribute(tmpEl, null, "SetAs", null, "owshiddenversion");

    tmpEl = AddFieldElement(doc, fieldsNode, "Attachments", "tp_HasAttachment", "Attachments", "Attachments", true, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "ModStat", "tp_ModerationStatus", "_ModerationStatus", "Approval Status", true, true, true);

    AddAttribute(tmpEl, null, "CanToggleHidden", null, "TRUE");

    AddAttribute(tmpEl, null, "Required", null, "FALSE");

    tmpEl = AddFieldElement(doc, fieldsNode, "Computed", null, "LinkTitleNoMenu", "Title", true, false, true);

    AddAttribute(tmpEl, null, "AuthoringInfo", null, "(linked to item)");

    AddAttribute(tmpEl, null, "Dir", null, "");

    AddAttribute(tmpEl, null, "DisplayNameSrcField", null, "Title");

    tmpEl = AddFieldElement(doc, fieldsNode, "Computed", null, "LinkTitle", "Title", true, false, true);

    AddAttribute(tmpEl, null, "AuthoringInfo", null, "(linked to item with edit menu)");

    AddAttribute(tmpEl, null, "DisplayNameSrcField", null, "Title");

    AddAttribute(tmpEl, null, "ClassInfo", null, "Menu");

    tmpEl = AddFieldElement(doc, fieldsNode, "Computed", null, "SelectTitle", "Select", true, true, true);

    AddAttribute(tmpEl, null, "AuthoringInfo", null, "(web part connection)");

    AddAttribute(tmpEl, null, "Dir", null, "");

    AddAttribute(tmpEl, null, "Sortable", null, "FALSE");

    AddAttribute(tmpEl, null, "CanToggleHidden", null, "TRUE");

    tmpEl = AddFieldElement(doc, fieldsNode, "Guid", "tp_Guid", "GUID", "GUID", true, true, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "FirstName", "FirstName", "FirstName", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "FullName", "FullName", "FullName", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "Email", "Email", "Email", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "Company", "Company", "Company", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "JobTitle", "JobTitle", "JobTitle", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "WorkPhone", "WorkPhone", "WorkPhone", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "HomePhone", "HomePhone", "HomePhone", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "CellPhone", "CellPhone", "CellPhone", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "WorkFax", "WorkFax", "WorkFax", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "WorkAddress", "WorkAddress", "WorkAddress", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "WorkCity", "WorkCity", "WorkCity", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "WorkState", "WorkState", "WorkState", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "WorkZip", "WorkZip", "WorkZip", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Text", "WorkCountry", "WorkCountry", "WorkCountry", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "URL", "WebPage", "WebPage", "WebPage", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Note", "Comments", "Comments", "Comments", false, false, true);

    tmpEl = AddFieldElement(doc, fieldsNode, "Date", "Birthday", "Birthday", "Birthday", false, false, true);

    // Return the XML

    return doc;

    <<< unsnip

    This code makes use of a function I added

    <<< snip

           private static XmlElement AddFieldElement(XmlDocument parentDoc, XmlNode parentNode, string type, string colName, string name, string displayName, bool readOnly, bool hidden, bool fromBaseType)

           {

               XmlElement fieldEl = parentDoc.CreateElement(null, "Field", _wssns);

               parentNode.AppendChild(fieldEl);

               if (type != null) AddAttribute(fieldEl, null, "Type", null, type);

               if (colName != null) AddAttribute(fieldEl, null, "ColName", null, colName);

               if (name != null) AddAttribute(fieldEl, null, "Name", null, name);

               if (displayName != null) AddAttribute(fieldEl, null, "DisplayName", null, displayName);

               if (readOnly) AddAttribute(fieldEl, null, "ReadOnly", null, "TRUE");

               if (hidden) AddAttribute(fieldEl, null, "Hidden", null, "TRUE");

               if (fromBaseType) AddAttribute(fieldEl, null, "FromBaseType", null, "TRUE");

               return fieldEl;

           }

    <<< unsnip

  49. Kirill Vinokurov says:

    Thanks Stephen and Paul Linton.

    All work fine!

    You can display the contacts in Outlook with photos using this provider?

  50. Mikes says:

    Thanks this is great!

    Been looking for something like this for a while.

    Has anyone updated it so it allows 2-way sync (update info from Outlook)?

  51. test_10 says:

    when this code run on vs2005 then get error msdn.outlook.contacts.global ambiguous.