Microsoft Dynamics CRM 2011 is the latest version of Microsoft’s CRM platform. Both the hosted (SaaS) version and on-site versions are now available for production solutions. Unlike previous versions of Dynamics
CRM, the 2011 release does NOT have a BizTalk-specific send adapter. The stated guidance is to use the existing SOAP endpoints through the BizTalk WCF adapter.
In this post, I’ll show you what it takes to perform both “query” and “create” operations against Dynamics CRM 2011 using BizTalk Server.
Before you start, you have a choice to make. Dynamics CRM 2011 has a diverse set of integration options (see MSDN page on Web Service integration here). They have a very nice REST interface
for interacting with standard and custom entities in the system. BizTalk Server can’t talk “REST”, and the REST services can only be used within the Dynamics CRM application itself, so that’s not an option. They have an ASMX endpoint for legacy clients,
and that is available for BizTalk consumers. The final option is their new WCF SOAP endpoint. Microsoft made a distinct choice to build an untyped interface into their SOAP service. That is, the operations like
Create or Update take in a generic Entity object. An Entity has a name and a property bag of name/value pairs that hold the record’s columns and values. If you are a building a .NET client to call Dynamics
CRM 2011, you can use the rich SDK provided and
generate some early bound classes which can be passed to a special proxy class (OrganizationServiceProxy) which hides the underlying translation between typed objects and the Entity object. There’s a special WCF behavior (ProxyTypesBehavior) in play there
too. So for .NET WCF clients, you don’t know you’re dealing with an untyped SOAP interface.
For non-.NET clients, or software that can’t leverage their SDK service proxy, you have to use the untyped interface directly.
So in real life, your choice as a BizTalk developer will have to be either
(a) deal with challenges of creating and consuming untyped messages, or
(b) build proxy services for BizTalk to invoke that take in typed objects and communicate to Dynamics CRM. In the future, I hope that the Microsoft team will ship a WCF behavior that could be added to the BizTalk WCF adapter that would do this typed-to-untyped
translation both inbound and outbound
In this post, I’ll show option A which includes dealing directly with the bare Entity message type.
First off, we need to add a reference to the SOAP endpoint. Within Dynamics CRM, all the links to service endpoints can be found in the
Customization menu under Developer Resources. I’ve chosen the Organization Service which has a WSDL to point to.
Within a BizTalk project in Visual Studio.NET, I added a generated item, and chose to consume a WCF service. After added the reference, I get a ton of generated artifacts.
Now in an ideal world, these schemas would be considered valid. Alas, that is not the case. When opening the schemas, a number of errors are displayed. Apparently there is a lot of cross-schema-referencing missing from the schemas. You could choose to
manually correct these links, or, browse to the Dynamics CRM 2011 SDK and include the provided BizTalk schemas in your project and delete the generated schemas.
For my simple demo scenario, I have a single message that holds details used for both querying and creating CRM records. It holds the GUID identifier for a record in its
Query node and in its Create node, it has a series of record attributes to apply to a new record.
Retrieving a record is pretty simple. In this case, all you need to populate is the name of the entity (e.g. “contact”, “account”, “restaurant”), the record identifier, and which columns to retrieve. In my map, I’ve set the
AllColumns node to true which means that everything comes back. Otherwise, I’d need some custom XSLT in a functoid to populate the
The “create” message is more complicated as we need to successfully build up a set of name/value pairs. Let’s walk through the steps.
The first “page” of my map links the entity’s name and sets a few unused elements to null.
Now it gets fun. You see a node there named KeyValuePairOfstringanyType. This node is repeated for each column that I want to populate in my created Entity. I’m going to show one way to populate it; there are others. On this map page,
I’ve connected each source node (related to a column) to a Looping functoid. This will allow me to create one
KeyValuePairOfstringanyType for each source node.
Now I have to actually map the name and value across. Let’s break this into two parts. First, I need to get the node name into the “key” field. We can do this by dragging each source node to the “key” field, and setting the map link’s
Source Links property to Copy Name. This copies the name of the node across, not the value.
So far so good. Now I need the node’s value. You might say, “Richard, that part is easy.” I’ll respond with “Nothing is easy.” No, the node’s name,
KeyValuePairOfstringanyType, gives it away. I actually need to set an XSD “type” property on the “value” node itself. If I do a standard mapping and call the service, I get a
serialization error because the data type of the “value” node is xsd:anyType and Dynamic CRM expects us to tell it which type the node is behaving like for the given column. Because of this, I’m using a Scripting functoid to manually define
the “value” node and attach a type attribute.
My functoid uses the Inline XSLT Call Template script type and contains the following:
I also built an orchestration that calls the service and spits the result to disk, but there’s not much to that. At this point, I deployed the solution.
Now within the BizTalk Admin Console, I imported one of the bindings that the WCF Service Consuming Wizard produced. This makes life simple since there’s virtually nothing you have to change in the BizTalk send port that this binding produces.
The WCF-Custom adapter uses a custom WCF binding.
The only thing I added was on the Credentials tab, I added my Windows credentials for calling the service. After creating the necessary receive port/location to pick up my initial file, send port to emit the service result to disk, and
bound my orchestration, I was ready to go.
In my Dynamics CRM environment, I added a customer account record for “Contoso”. You can see a few data points which should show up in my service result when querying this record.
After calling the “Query” operation, I can see the result of the service call. In reality, you’d have to build some mapping between this result and a canonical schema.
As for creating the record, when I send my command message in to create a new record, I see the new (Fabrikam) record in Dynamics CRM and a file on disk with the unique identifier for the new record.
An architect of a BizTalk Server 2011 integration with Dynamics CRM 2011 has to decide whether to use proxy components to call the CRM services, or perform the typed-to-untyped mapping exercise within the BizTalk solution. This post showed a couple of strategies
for the latter strategy.