Welcome to a new series on the Microsoft Dynamics CRM for Outlook Client Synchronization. This series was written by one of our Sr. Support Engineers, Derek Braun. The series will continue over the next few months with a lot of great detail into the synchronization process.

Introduction

Have you ever wondered what happens when you click on Track in CRM? Or how about what happens when you click Synchronize with CRM? This blog series will explain both of these processes, as well as general troubleshooting tips and guidelines to help illustrate the entire CRM 2011 Outlook client synchronization procedure.

Our first entry into this series is centered on all of the actions that occur when users track non e-mail Outlook objects, such as Contacts, into Microsoft Dynamics CRM.

What Happens When an Item is Tracked – Part 1

When a user clicks the "Track in CRM" button, the CRM Outlook add-in performs several functions which include:

  1. The web service request to create (promote) the record on the server.
  2. An insert on the OutlookSyncTable, located in the OutlookSyncCache local database.
  3. An insert on the idMappingTable, also located in the OutlookSyncCache, to map the Outlook entry ID to the CRM record ID for future reference.
  4. The creation of user-defined fields in the Outlook item.

The first three items above are performed immediately when the track is committed. Then, before the client can create the user-defined fields in step 4, the server must perform several actions, which include:

  • Checking the user’s security privilege level.
  • Running duplicate detection, if applicable.
  • Invoking internal or 3rd party synchronous plugins, if applicable.
  • Creating the actual record.
  • Inserting a row into the user’s SyncEntry table.
  • Sending the create response back to the client, containing the CRM record’s GUID.

If any of the above actions on the server cannot be completed, the track process will fail. Each of these processes is explained in detail below.

Web Service Create Request

The track process is synchronous for non-e-mail objects. This means that the track request is transmitted immediately to the server when the user clicks the Track button from the explorer, or when the user clicks Track and then ‘Save and Close’ in the inspector.  The Explorer view is the list view of items in Outlook, while the Inspector view is the open item’s form. This is illustrated in the screenshots below:

Explorer View

Inspector View

This is why users may sometimes notice a slight delay when they click “Save and Close” after tracking an item in the Inspector, as the window will not finish closing until the track process is complete. The reason why users must click Save and Close in the Inspector to commit the track request is to account for any other changes that might be made to the Outlook item before the user finishes working with the record. For example, when working in an Outlook contact, users could click “Track”, and then modify the phone number field afterwards. Then, when the user clicks “Save and Close”, the phone number change will be included in the initial create request that is sent to the server.

As part of the initial SDK create request, the Messaging API (MAPI) properties of the Outlook item are retrieved by the add-in and passed to the CRM platform over the organization web service.  The location of the MAPI store depends on whether or not the user has enabled Exchange Cached Mode. When Exchange Cached Mode is enabled, the add-in is able to retrieve the MAPI properties of an item locally without contacting the Exchange server. This is made possible by the caching of the user’s mailbox to a local .OST file that maintains synchronization of all mailbox items with Exchange. When Exchange Cached Mode is disabled, the add-in must retrieve these properties from the Exchange server. While the add-in should retrieve the same information regardless of this setting, it is something to keep in mind when troubleshooting.

The MAPI properties of an item can be thought of as the data attributes of an Outlook object, which are then used to map to similar fields in CRM. For example, when tracking a Contact, the create request sent by the client will include the “First Name” MAPI property (PR_Given_Name) of the contact in Outlook, which would then correspond to the First Name field (firstname) in the resulting contact record in CRM. MAPI properties also extend to many other attributes that Outlook uses to manage objects internally, such as unique identifiers (PR_EntryID) or timestamp information (PR_Creation_Time) that isn’t normally visible to the end user. Programs like OutlookSpy or MFC Mapi can be used to inspect and modify individual MAPI properties, although users should exercise caution when operating such tools.

In addition to these fields, the create request will also contain the CRM user’s SubscriptionID, which is then used to tie the user’s unique subscription to the contact in the ContactBase table. This is done to identify which user had originally tracked the contact into CRM. This is done so that if the contact should ever be deleted in the application, the contact will only be “untracked” in Outlook instead of deleted when the client performs a subsequent synchronization. The full logic behind how the Outlook client handles deletes in both CRM and Outlook will be discussed in a future article in this series.

The response to this request will contain the corresponding CRM record’s GUID. You can use tools like Fiddler or WCF Tracing to capture this request/response, or even run a platform trace on the CRM server while tracking the object. The use of these tools will be covered in greater detail in a future blog article in this series.  The request and response to the track action are transmitted over the wire in the form of XML, and are shown below. The following example illustrates the Create Request of a Contact.

Request:

<s:Body>

  <Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">

    <request i:type="b:CreateRequest" xmlns:b="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

      <b:Parameters xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic">

        <b:KeyValuePairOfstringanyType>

          <c:key>Target</c:key>

          <c:value i:type="b:Entity">

            <b:Attributes>

              <b:KeyValuePairOfstringanyType>

                <c:key>telephone1</c:key>

                <c:value i:type="d:string" xmlns:d="http://www.w3.org/2001/XMLSchema">(701) 555-0135</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>emailaddress1</c:key>

                <c:value i:type="d:string" xmlns:d="http://www.w3.org/2001/XMLSchema">someone_b@example.com</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>address1_line1</c:key>

                <c:value i:type="d:string" xmlns:d="http://www.w3.org/2001/XMLSchema">5979 El Pueblo</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>address1_city</c:key>

                <c:value i:type="d:string" xmlns:d="http://www.w3.org/2001/XMLSchema">Issaquah</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>address1_stateorprovince</c:key>

                <c:value i:type="d:string" xmlns:d="http://www.w3.org/2001/XMLSchema">WA</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>address1_postalcode</c:key>

                <c:value i:type="d:string" xmlns:d="http://www.w3.org/2001/XMLSchema">23382</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>address1_country</c:key>

                <c:value i:type="d:string" xmlns:d="http://www.w3.org/2001/XMLSchema">U.S.</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>firstname</c:key>

                <c:value i:type="d:string" xmlns:d="http://www.w3.org/2001/XMLSchema">Maria</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>lastname</c:key>

                <c:value i:type="d:string" xmlns:d="http://www.w3.org/2001/XMLSchema">Campbell (sample)</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>donotemail</c:key>

                <c:value i:type="d:boolean" xmlns:d="http://www.w3.org/2001/XMLSchema">false</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>donotpostalmail</c:key>

                <c:value i:type="d:boolean" xmlns:d="http://www.w3.org/2001/XMLSchema">false</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>donotbulkemail</c:key>

                <c:value i:type="d:boolean" xmlns:d="http://www.w3.org/2001/XMLSchema">false</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>donotbulkpostalmail</c:key>

                <c:value i:type="d:boolean" xmlns:d="http://www.w3.org/2001/XMLSchema">false</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>donotphone</c:key>

                <c:value i:type="d:boolean" xmlns:d="http://www.w3.org/2001/XMLSchema">false</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>donotfax</c:key>

                <c:value i:type="d:boolean" xmlns:d="http://www.w3.org/2001/XMLSchema">false</c:value>

              </b:KeyValuePairOfstringanyType>

              <b:KeyValuePairOfstringanyType>

                <c:key>subscriptionid</c:key>

                <c:value i:type="d:guid" xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/">93dc719d-8e14-e211-a107-00155d52f309</c:value>

              </b:KeyValuePairOfstringanyType>

            </b:Attributes>

            <b:EntityState i:nil="true"/>

            <b:FormattedValues/>

            <b:Id>00000000-0000-0000-0000-000000000000</b:Id>

            <b:LogicalName>contact</b:LogicalName>

            <b:RelatedEntities/>

          </c:value>

        </b:KeyValuePairOfstringanyType>

        <b:KeyValuePairOfstringanyType>

          <c:key>SuppressDuplicateDetection</c:key>

          <c:value i:type="d:boolean" xmlns:d="http://www.w3.org/2001/XMLSchema">false</c:value>

        </b:KeyValuePairOfstringanyType>

      </b:Parameters>

      <b:RequestId i:nil="true"/>

      <b:RequestName>Create</b:RequestName>

    </request>

  </Execute>

</s:Body>

Response:

  <s:Body>

    <ExecuteResponse xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">

      <ExecuteResult i:type="b:CreateResponse" xmlns:b="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

        <b:ResponseName>Create</b:ResponseName>

        <b:Results xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic">

          <b:KeyValuePairOfstringanyType>

            <c:key>id</c:key>

            <c:value i:type="d:guid" xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/">99f361d3-6645-e211-a107-00155d52f309</c:value>

          </b:KeyValuePairOfstringanyType>

        </b:Results>

      </ExecuteResult>

    </ExecuteResponse>

  </s:Body>

 

Continue to part 2