|Read more about this book|
(For more resources on BizTalk, see here.)
The second place where Dynamics CRM can communicate with BizTalk Server is through workflows. A workflow in Dynamics CRM is an automated process where a set of steps is executed according to rules that we define. For example, when a sales opportunity is closed, we run a workflow that adds a message to the customer record, notifies all parties tied to the opportunity, and sends a polite email to the lost prospect. Workflows are based on Windows Workflow 4.0 technology and can be built either in the Dynamics CRM application itself or within Visual Studio 2010. The Dynamics CRM web application allows us to piece together workflows using previously registered workflow steps. If we need new workflow steps or need to construct something complex, we can jump into Visual Studio 2010 and define the workflow there. Why would we choose to use a workflow to send a message to BizTalk Server? If you have a long-running process that can either be scheduled or executed on demand, and want the option for users to modify the process, then workflow may be the right choice.
The final strategy for communicating between Dynamics CRM and BizTalk Server is to use plugins. Plugins are server-based application extensions that execute business logic and get tied directly to an entity. This means that they are invoked whether we work in the Dynamics CRM web interface or through the API. I can run a plugin both synchronously and asynchronously, depending on the situation. For instance, if we need to validate the data on a record prior to saving it, we can set a plugin to run before the "save" operation is committed and provide some user feedback on the invalid information. Or, we could choose to asynchronously call a plugin after a record is saved and transmit data to our service bus, BizTalk Server. In the following exercise, we will leverage plugins to send data from Dynamics CRM to BizTalk Server.
Integration to BizTalk Server
In this first walkthrough, we will build a plugin that communicates from Dynamics CRM to a BizTalk Server located. An event message will be sent to BizTalk whenever a change occurs on an Account record in Dynamics CRM.
This exercise leverages a BizTalk Server project already present in your Visual Studio 2010 solution. We are going to publish a web service from BizTalk Server that takes in a message and routes it to a BizTalk send port that writes the message to the file system.
- If you have not already done so, go to the code package and navigate to C:\LOBIntegration\Chapter03\Chapter3-DynamicsCRM and open the Visual Studio 2010 solution file named Chapter3-DynamicsCRM.sln.
- Find the BizTalk Server project named Chapter3-DynamicsCRM.AcctRouting and open it.
- The code package includes a custom schema named AccountEventChange_XML.xsd and notice which elements we want from Dynamics CRM 2011 when an account changes. The first element, EventSource, is used to designate the source of the change event, as there may be multiple systems that share changes in an organization's accounts.
- This BizTalk project should be set to deploy to a BizTalk application named Chapter3. Build and deploy the project to the designated BizTalk Server.
- After confirming a successful deployment, launch the BizTalk WCF Service Publishing Wizard. We are going to use this schema to expose a web service entry point into BizTalk Server that Dynamics CRM 2011 can invoke.
- On the WCF Service Type wizard page, select a WCF-BasicHttp adapter and set the service to expose metadata and have the wizard generate a receive location for us in the Chapter3 application:
- On the Create WCF Service wizard page, choose to Publish schemas as WCF service. This option gives us fine-grained control over the naming associated with our service.
- On the next page, delete the two-way operation already present in the service definition. Rename the topmost service definition to AccountChangeService and assign the service the same name. Right-click the service and create a new one-way operation named PublishAccountChange. Right click the Request message of the operation and choose the AccountChangeEvent message from our BizTalk Project's DLL:
- On the following wizard page, set the namespace of the service to http://Chapter3/AccountServices.
- Next, set the location of our service to http://localhost/AccountChangeService and select the option to allow anonymous access to the generated service. Finally, complete the wizard by clicking the Create button on the final wizard page.
- Confirm that the wizard successfully created both an IIS-hosted web service, and a BizTalk receive port/location. Ensure that the IIS web service is running under an Application Pool that has permission to access the BizTalk databases.
- In order to test this service, first go to the BizTalk Server Administration Console and locate the Chapter3 application.
- Right click the Send Ports folder and create a new, static one-way send port named Chapter3.SendAccountChange.FILE. Set the send port to use the FILE adapter and select the FileDrop\DropCustomerChangeEvent folder that is present in the code package:
- This send port should listen for all account change event messages, regardless of which receive location (and system) that they came from. Go to the Filters tab of this send port. Set the filter Property to BTS.MessageType and filter Value to http://Chapter3-DynamicsCRM.AcctRouting.AccountChangeEvent_XML#AccountChangeEvent.
- All that remains is to test our service. Open the WCF Test Client application and add a new service reference to http://localhost/AccountChangeService/AccountChangeService.svc.
- Invoke the PublishAccountChange method and, if everything is configured correctly, we will see a message emitted by BizTalk Server that matches our service input parameters:
(Move the mouse over the image to enlarge.)
We now are sufficiently ready to author the Dynamics CRM plugin, which calls this BizTalk service.
|Read more about this book|
(For more resources on BizTalk, see here.)
Writing the Dynamics CRM plugin
A Dynamics CRM plugin is a powerful way to extend the out-of-the-box behavior of the product with custom code. The plugin that we are building for this exercise invokes the service we built above.
Before starting, ensure that you have downloaded the Dynamics CRM 2011 SDK and installed the microsoft.xrm.sdk.dll assembly in the Global Assembly Cache.
- In the existing Chapter3-DynamicsCRM Visual Studio 2010 solution, add a new Class Library project named Chapter3-DynamicsCRM.AcctPlugin to the solution.
- Add a new reference to this project and point to the microsoft.xrm.sdk.dll assembly. This assembly contains the interfaces and types that we need to correctly define a plugin.
- Now, we need a service reference to our BizTalk-generated WCF endpoint. Choose to add a new Service Reference to the project. Point to our previously created service and set the namespace to AcctChangeSvc:
- Add a new class file named AccountEventPlugin.cs to the project.
- At the top of the new class, add two additional "using" statements pointing to Microsoft.Xrm.Sdk and System.ServiceModel. These assemblies have all that we need to define the plugin and consume our BizTalk-generated service.
- The public class should implement the IPlugin interface, which has a single required operation, named Execute:
public class AccountEventPlugin : IPlugin
public void Execute(IServiceProvider serviceProvider)
- Depending on your use case, you may need to store the result of a successful plugin invocation on a Dynamics CRM record. In this scenario, we will simply log details of our plugin execution to the machine's Event Log. Hence the first line in the Execute operation is as follows:
WriteEntry("Application", "Plugin invoked successfully", System.
- Next up, we need to acquire context about the data entity being passed to the plugin. The IPipelineExecutionContext holds such information in addition to the runtime environment that the plugin is executing in:
IPluginExecutionContext context = (IPluginExecutionContext)
- We will be extracting data from an Account, and thus need a variable that references this entity. At the time of declaring this variable, its value is null:
Entity accountEntity = null;
- Because one can use a plugin in all sorts of scenarios, some preventative error checking is prudent. To start with, we can ensure that the object that was passed into the plugin is indeed a Dynamics CRM entity. The context object defined earlier contains a set of input parameters containing the data from the request message:
if (context.InputParameters.Contains("Target") && context.
InputParameters["Target"] is Entity)
- If the plugin target is an entity, set the previously defined accountEntity variable to the entity passed into the plugin:
//retrieve entity from input params
accountEntity = (Entity)context.InputParameters["Target"];
- We could have tied this plugin to any Dynamics CRM entity and therefore should check and make sure that the type of entity passed into the plugin is valid:
//if the target account type isn't "account" exit
if (accountEntity.LogicalName != "account")
"Target is not 'account' type",
- One key thing to realise is that when the "Update" events occur in the Dynamics CRM event pipeline, only the changed fields of an entity are put in the context's property bag. In order to have access to the entire payload of the account entity, we can use an Image. An Image is a representation of an entity either before or after it was saved to Dynamics CRM. There are four fields of the Account entity that we are interested in and those can be retrieved from the PostEntityImages collection that is part of the context. We use the name "PostEventImage" here and will refer to it later when we register this plugin with Dynamics CRM:
Entity acctImage = context.PostEntityImages["PostEventImage"];
string acctName = accountEntity["name"].ToString();
string acctNumber = accountEntity["accountnumber"].ToString();
string state = accountEntity["address1_stateorprovince"].
string phone = accountEntity["telephone1"].ToString();
- Armed with the necessary data elements, we can now create the WCF service input object. The AccountChangeEvent object is defined as part of the Service Reference established previously:
AcctChangeSvc.AccountChangeEvent acct = new AcctChangeSvc.
acct.EventSource = "Dynamics CRM";
acct.AccountName = acctName;
acct.AccountNumber = acctNumber;
acct.PrimaryState = state;
acct.PrimaryPhoneNumber = phone;
- We are now ready to invoke the service from code. First, create a reference to the binding type associated with our BizTalk-generated service. In this example, use the BasicHttpBinding without any security settings turned on:
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityM
- Next, an endpoint address is required. Put in the full service URL associated with your BizTalk endpoint:
EndpointAddress addr = new EndpointAddress("http://localhost/
- This information is all that is needed to instantiate the service client that was defined in our Service Reference:
AcctChangeSvc.AccountChangeServiceClient client =
new AcctChangeSvc.AccountChangeServiceClient(binding, addr);
- Invoke thePublishAccountChange operation and upon success, write a message to the machine's Event Log:
"Service called successfully",
The plugin is now ready for deployment and registration in the Dynamics CRM environment
|Read more about this book|
(For more resources on BizTalk, see here.)
Registering the plugin
Microsoft provides a plugin registration tool as part of the SDK. This tool is located in the SDK\Tools\PluginRegistration folder of the SDK. Prior to running the plugin registration tool, copy the Chapter3-DynamicsCRM.AcctPlugin.dll to the <installation directory>\Program Files\Microsoft CRM\server\bin\assembly on the servers where Dynamics CRM resides. You need to put the assembly here if you want to debug it later or if you are not using the database storage option. If you do choose to store the plugin assembly in the Dynamics CRM database and are not concerned about debugging your plugin, then the assembly may reside anywhere during registration:
- The plugin registration tool is included in the Dynamics CRM SDK as an example application. Go to the location where we unpacked the SDK and navigate to the tools\pluginregistration folder. Build the project and launch the executable.
- Connect to the Dynamics CRM 2011 instance.
- Click the option to register a new assembly:
- Navigate to the Chapter3-DynamicsCRM.AcctPlugin.dll assembly and click Load Assembly.
- Specify the Isolation Mode as None. There is an additional option of Sandbox that introduces a series of limitations on plugins run in that mode. Sandboxed plugins have limits on access to the file system, Event Log, network, and more. This is a very useful option when offering a hosting environment, as a provider can restrict the types of plugins that each customer in the shared environment can deploy.
- Next, choose the location to store the plugin. The default option is Database but we may also store the file on disk or the Global Assembly Cache. Set the location as Database.
- Click the Registered Selected Plugins button to load and register the plugin in the Dynamics CRM database:
- Next up, within the Registered Plugins & Custom Workflow Activities window, select our new plugin, and choose Register and then Register New Step from the menu.
- This window lets us register the event and entity that should trigger our plugin. Set the event, called a message in Dynamics CRM, to Update. There are many message options, including Create, Close, Merge, Retrieve, and more.
- Set the Primary Entity value to account. This is the entity whose message will launch the plugin. Note that by using the Filtering Attributes property, we can set which fields on an entity trigger the message.
- Set the Eventing Pipeline Stage of Execution to Post-operation. Plugins run within the execution pipeline of entity processing. Plugins that run in the "pre" stage operate before the message is saved to Dynamics CRM. It is a useful place for doing data validation. The "post" stage is a good place for logic that should run after the data is committed to Dynamics CRM. In our case, we want to send the message to BizTalk Server after the entity has been updated. Select the radio button next to Post-operation.
- Finally, set the execution mode. Plugins can run either synchronously or asynchronously. A plugin that validates data before saving it should run synchronously so that the user can be notified if any errors are encountered. In this case, our service should execute after the Dynamics CRM user has finished updating the entity and we do not want to interrupt or delay the user while the BizTalk service is called. Set the Execution Mode to Asynchronous:
- With the step registered, our last step is to register an Image. Recall that the Update message only contains the fields that have undergone a change. If we need to access other fields from the entity, we either have to invoke the Dynamics CRM services, or, even better, use an Image that gets passed into the plugin. Select the plugin from the Registered Plugins & Custom Workflow Activities window, select the Register, and then the Register New Image button.
- Set the Image Type as Post Image, and set the Name and Entity Alias to PostEventImage. The Parameters setting allows us to set which fields on the entity we want available in the Image. Leave this value as All Attributes. Finally, click the Register Image button.
- At this point, our configuration should look like this:
We have now successfully built a Dynamics CRM 2011 plugin and registered it with the system. This plugin will asynchronously fire after an account record has been saved and pass a complete image within the IPluginExecutionContext object.
Testing the plugin
To test this configuration, we simply need to change the details on a specific account. Because we registered this plugin to fire on any change to an account entity (vs. filtering which attributes launch the plugin), any changed attribute will do:
- Open Dynamics CRM 2011 and navigate to the Accounts view.
- Open any existing account to view its attributes.
- Change any one attribute of the account. In the example above, I changed the account number from 10094 to 10095. The plugin should launch nearly immediately. Check the Event Log of the machine hosting Dynamics CRM 2011 and watch for the events signifying success.
- Next, switch to the folder that BizTalk Server sends the account change events to and confirm that the event was published there.
This simple test showed how a change in a Dynamics CRM entity could immediately send a message to BizTalk Server for additional processing.
To send messages from Dynamics CRM to BizTalk Server, we have numerous choices, including the plugin model. As Dynamics CRM 2011 matures in the market, expect to see additional creative ways to integrate it with BizTalk Server.
- Consuming the Adapter from outside BizTalk Server [Article]
- Integrating BizTalk Server and Microsoft Dynamics CRM [Article]
- New SOA Capabilities in BizTalk Server 2009: WCF SQL Server Adapter [Article]
- BizTalk Server: Standard Message Exchange Patterns and Types of Service [Article]
- The core principles of a service-oriented architecture with BizTalk Server 2009 [Article]
- SOA Patterns with BizTalk Server 2009 [Book]