Introducing the Diesel Xrm Service Wrapper

In this post, I will present a generic Windows Communication Foundation (WCF) wrapper for the Dynamics CRM Organization Service that lets you turn any FetchXML query into a web service interface without needing to write any code at all. I call my solution the Diesel Xrm Service Wrapper after Diesel, my Great Dane. Just like the CRM Organization Service, he's big and sometimes aggravating, so it's a perfect name!

Diesel the Dynamics CRM Great Dane

Usually I like to go into a lot of detail in my blog posts, but frankly WCF gives me such a headache that today I'm just going to explain how the things work at a high level and offer the solution for download without much commentary.

An administrator stores predefined FetchXML queries on the server where the service is hosted. The service's consumers all access a single endpoint, and a "query" parameter is used to load and execute the correct FetchXML query. The consumers authenticate using Dynamics CRM credentials, and a service account executes the queries while impersonating the calling user so that native Dynamics CRM security functionality authorizes all data requests.

Initial Configuration

First, download the solution here: DieselXrmSvcWrapper.zip (Updated Aug. 5, 2013 - This project is now hosted on GitHub. The original solution file download link in this post has been left unchanged, however.)

To configure the solution, you store the URL for your Dynamics CRM server and credentials for a user account to be used as a service account in the appSettings section of the web.config file. The service account should have fairly broad read permissions, including "Act On Behalf Of Another User." You can also modify the WCF configuration if you want to use different bindings or security modes. In the solution download, I'm using a basicHttpBinding with a "UserName" message clientCredentialType (that's WCF-speak for HTTP basic authentication over SSL).

Query Definition

After you've finished the configuration, you can now create the FetchXML queries that will be used for the actual web service interfaces. The queries are stored in individual XML files in a specific directory on the web server, and when a web service consumer calls the service, the "query" parameter maps queries to requests.

In addition to predefined FetchXML, queries can contain paramter substitution placeholders in the format of {$PARAMETER_NAME} that will be replaced with values supplied by the web service consumer. Here's an example query that is stored in a file called contacts.xml:

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">  
 <entity name="contact">  
 <attribute name="fullname" />  
 <attribute name="contactid" />  
 <attribute name="ownerid" />  
 <attribute name="address1_stateorprovince" />  
 <attribute name="gendercode" />  
 <attribute name="createdon" />  
 <order attribute="fullname" descending="false" />  
 <filter type="and">  
 <condition attribute="lastname" operator="like" value="{$lastnameletter}%" />  
 </filter>  
 </entity>  
</fetch>  

Sample SOAP Messages

Here's what the corresponding SOAP request method for the query above looks like:

<soapenv:Envelope  
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"   
 xmlns:tem="http://tempuri.org/"   
 xmlns:dies="http://schemas.datacontract.org/2004/07/DieselXrmSvcWrapper"  
 xmlns:i="http://www.w3.org/2001/XMLSchema-instance">  
 <soapenv:Header/>  
 <soapenv:Body>  
 <tem:Retrieve>  
 <tem:query>contacts</tem:query>  
 <tem:inputParameters>  
 <!--Zero or more repetitions:-->  
 <dies:ParameterItem>  
 <dies:Name>lastnameletter</dies:Name>  
 <dies:Value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">C</dies:Value>  
 </dies:ParameterItem>  
 </tem:inputParameters>  
 </tem:Retrieve>  
 </soapenv:Body>  
</soapenv:Envelope>  

The number of ParameterItems in the request should match the number of substitution placeholders in the query. If there are no placeholders, then you should omit the InputParameters section completely.

The SOAP response for the request above is attached here: soap-response.txt.

Wrapping Up

Now that you understand how the solution behaves and how to configure it, here's an overview of the solution components:

  1. FetchXML queries - As mentioned above, each query is stored in a separate XML file in a single directory. In my solution, the directory is called "RetrieveQueries," but you can change it in the web.config file.
  2. CrmUsernamePasswordValidator.cs - This custom username/password validator lets WCF validate the Dynamics CRM user credentials via TransportWithMessageCredential security. This also stores the users' CRM roles in an HttpContext.User object, so you could add some sort of role-based authorization to your service if you want.
  3. SoapSvc.svc - This actually does the request/response processing.

Once you have everything set up, you'll want to try it out, and I suggest using SoapUI. To get up and running with SoapUI, you basically just point it at your service's auto-generated WSDL, and SoapUI will figure out most everything it needs to work. If you use my solution without modifying the WCF configuration, you will need to change the WSS-Password Type setting for your request to "PasswordText," and you'll have to supply the username and password either in the request properties menu or on the Authorization tab. I've circled these fields in the screenshot below.

SoapUI

In the future, I plan to update the solution to handle create/update/delete requests, and I may look at setting up a REST interface, too. If you have any thoughts or feedback, please share in the comments.

Happy web service wrapping!

comments powered by Disqus