<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[FetchXML - Alexander Development]]></title><description><![CDATA[FetchXML - Alexander Development]]></description><link>https://alexanderdevelopment.net/</link><image><url>https://alexanderdevelopment.net/favicon.png</url><title>FetchXML - Alexander Development</title><link>https://alexanderdevelopment.net/</link></image><generator>Ghost 1.20</generator><lastBuildDate>Thu, 23 Apr 2026 16:47:46 GMT</lastBuildDate><atom:link href="https://alexanderdevelopment.net/tag/fetchxml/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Updated solution for scheduling recurring Dynamics 365 workflows]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've released an updated version of my recurring workflow scheduler for Dynamics 365 Customer Engagement. This solution targets Dynamics 365 version 9, so it should work in all current Dynamics 365 online organizations. You can download version 1.3 of my solution from here: <a href="https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner/releases/tag/v1.3">https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner/</a></p></div>]]></description><link>https://alexanderdevelopment.net/post/2018/03/12/updated-solution-for-scheduling-recurring-dynamics-crm-workflows-2/</link><guid isPermaLink="false">5aa6908f44999a000186ddb1</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[Dynamics 365]]></category><category><![CDATA[utilities]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[process automation]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Mon, 12 Mar 2018 15:00:00 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2018/03/chrome_2018-03-12_09-40-49.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2018/03/chrome_2018-03-12_09-40-49.png" alt="Updated solution for scheduling recurring Dynamics 365 workflows"><p>I've released an updated version of my recurring workflow scheduler for Dynamics 365 Customer Engagement. This solution targets Dynamics 365 version 9, so it should work in all current Dynamics 365 online organizations. You can download version 1.3 of my solution from here: <a href="https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner/releases/tag/v1.3">https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner/releases/tag/v1.3</a>.</p>
<p>For more information on the use of this tool, take a look at the original blog posts:</p>
<ul>
<li><a href="https://alexanderdevelopment.net/post/2016/09/19/updated-solution-for-scheduling-recurring-dynamics-crm-workflows/">https://alexanderdevelopment.net/post/2016/09/19/updated-solution-for-scheduling-recurring-dynamics-crm-workflows/</a></li>
<li><a href="https://alexanderdevelopment.net/post/2013/05/18/scheduling-recurring-dynamics-crm-workflows-with-fetchxml/">https://alexanderdevelopment.net/post/2013/05/18/scheduling-recurring-dynamics-crm-workflows-with-fetchxml/</a></li>
</ul>
</div>]]></content:encoded></item><item><title><![CDATA[Updated solution for scheduling recurring Dynamics CRM workflows]]></title><description><![CDATA[<div class="kg-card-markdown"><p>About three years ago I released an <a href="https://alexanderdevelopment.net/post/2013/05/19/scheduling-recurring-dynamics-crm-workflows-with-fetchxml/">open source Dynamics CRM solution for scheduling and executing recurring workflows</a>. My solution would execute a FetchXML query to return a set of records and then start a workflow for each of those records without requiring any external processes or tools. This is</p></div>]]></description><link>https://alexanderdevelopment.net/post/2016/09/19/updated-solution-for-scheduling-recurring-dynamics-crm-workflows/</link><guid isPermaLink="false">5a5837246636a30001b97843</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[utilities]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[C#]]></category><category><![CDATA[programming]]></category><category><![CDATA[process automation]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Mon, 19 Sep 2016 21:07:07 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2016/09/chrome_2016-09-19_15-27-18-1.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2016/09/chrome_2016-09-19_15-27-18-1.png" alt="Updated solution for scheduling recurring Dynamics CRM workflows"><p>About three years ago I released an <a href="https://alexanderdevelopment.net/post/2013/05/19/scheduling-recurring-dynamics-crm-workflows-with-fetchxml/">open source Dynamics CRM solution for scheduling and executing recurring workflows</a>. My solution would execute a FetchXML query to return a set of records and then start a workflow for each of those records without requiring any external processes or tools. This is a generalized approach to solving a class of problems that includes the following scenarios:</p>
<ol>
<li>The birthday greetings problem: How can you, on a daily basis, send an e-mail to every contact with a birthday = today (where the date value for today is obviously different every day)?</li>
<li>The monthly update problem: How can you, on a monthly basis, generate an activity for every account with status reason = X (where it's important that the process only runs on a certain day of the month based on status reason values as of that exact date)?</li>
</ol>
<p>Of all the CRM sample code and solutions I've ever shared, I think this was probably the most popular, but it had one glaring flaw. My original solution would only retrieve a maximum of 5,000 records per run because it didn't include any result paging code. Today I have released an updated version of my <a href="https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner/releases/tag/v1.1">solution for CRM 2016</a> that does include result paging, and I've also moved hosting for the solution source code to <a href="https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner">GitHub</a>.</p>
<h4 id="howitworks">How it works</h4>
<p>In case you're unfamiliar with the previous version of my solution, my approach requires three components (the names have changed in the updated version):</p>
<ol>
<li>A custom workflow activity (AlexanderDevelopment.WorkflowScheduler) that can execute a supplied FetchXML query and initiate the workflow for each retrieved record.</li>
<li>A custom entity (Recurring process) to hold the FetchXML query and scheduling details.</li>
<li>A workflow (Recurring workflow runner) to run the AlexanderDevelopment.WorkflowScheduler activity on a recurring schedule.</li>
</ol>
<p>A &quot;Recurring process&quot; record is created, which starts a corresponding &quot;Recurring workflow runner&quot; workflow in a timeout state. When the next run date == the current time, the &quot;Recurring workflow runner&quot; workflow advances the next run date, and then it initiates the AlexanderDevelopment.WorkflowScheduler activity with the FetchXML query and workflow lookup from the &quot;Recurring process&quot; record. The AlexanderDevelopment.WorkflowScheduler executes the FetchXML, loops through the results and starts the specified workflow from the lookup for each record. A newly started &quot;Recurring workflow runner&quot; workflow then waits for the next run date to start the process again.</p>
<p>Here's what a &quot;Recurring process&quot; record looks like:<br>
<img src="https://alexanderdevelopment.net/content/images/2016/09/chrome_2016-09-19_15-27-18.png#img-thumbnail" alt="Updated solution for scheduling recurring Dynamics CRM workflows"></p>
<p>Here's the &quot;Recurring workflow runner&quot; workflow:<br>
<img src="https://alexanderdevelopment.net/content/images/2016/09/chrome_2016-09-19_15-28-10.png#img-thumbnail" alt="Updated solution for scheduling recurring Dynamics CRM workflows"></p>
<p>The default result page size is 1,000, but you change it in &quot;Recurring workflow runner&quot; workflow definition:<br>
<img src="https://alexanderdevelopment.net/content/images/2016/09/chrome_2016-09-19_15-28-57.png#img-thumbnail" alt="Updated solution for scheduling recurring Dynamics CRM workflows"></p>
<h4 id="puttingitalltogether">Putting it all together</h4>
<p>As mentioned above, the source code for the solution is available in a GitHub repository <a href="https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner">here</a>. You can also download a CRM solution ready to load into your system directly from the repository <a href="https://github.com/lucasalexander/AlexanderDevelopment.ProcessRunner/releases/latest">releases area</a>.</p>
<p>Happy workflow scheduling!</p>
</div>]]></content:encoded></item><item><title><![CDATA[Console application for moving Dynamics CRM access team templates]]></title><description><![CDATA[<div class="kg-card-markdown"><p>When Dynamics CRM 2013 was released, I thought access teams were the new killer feature in that version, and I even developed custom workflow activity code to make <a href="https://alexanderdevelopment.net/post/2014/01/09/managing-microsoft-dynamics-crm-2013-access-team-membership-using-connections-2/">managing access team membership easier by using connection records</a>. I have thus far not had an opportunity to use access teams in</p></div>]]></description><link>https://alexanderdevelopment.net/post/2014/12/12/console-application-for-moving-dynamics-crm-access-team-templates/</link><guid isPermaLink="false">5a5837226636a30001b9775d</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[programming]]></category><category><![CDATA[C#]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[CRM 2013]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Sat, 13 Dec 2014 00:00:00 GMT</pubDate><media:content url="https://alexanderdevelopment.net/content/images/2015/10/team-mover-cli.PNG" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://alexanderdevelopment.net/content/images/2015/10/team-mover-cli.PNG" alt="Console application for moving Dynamics CRM access team templates"><p>When Dynamics CRM 2013 was released, I thought access teams were the new killer feature in that version, and I even developed custom workflow activity code to make <a href="https://alexanderdevelopment.net/post/2014/01/09/managing-microsoft-dynamics-crm-2013-access-team-membership-using-connections-2/">managing access team membership easier by using connection records</a>. I have thus far not had an opportunity to use access teams in a real project, so I was disappointed to read <a href="https://crmbusiness.wordpress.com/2014/12/01/crm-2013-why-are-access-teams-marooned/">this blog post</a> by Ben Hosking (AKA &quot;The Hosk&quot;) about how Microsoft doesn't provide any out-of-the-box capabilities for moving access team templates between Dynamics CRM organizations. In that post, the Hosk says, &quot;It’s possible someone could build a console app to import the access team templates but as yet no one has created it.&quot; Challenge accepted.</p>
<p>My CRM Access Team Mover tool is available for download <a href="https://github.com/lucasalexander/CrmAccessTeamMover/releases/tag/v1.0">here,</a> and the source code is available on <a href="https://github.com/lucasalexander/CrmAccessTeamMover">GitHub</a>.</p>
<p>To copy/update access team templates from one organization to another using my tool, do the following:</p>
<ol start="2">
<li>Execute the tool from the command line.</li>
<li>When prompted to enter the the source connection string, supply a complete <a href="http://msdn.microsoft.com/en-us/library/gg695810.aspx">Dynamics CRM simplified connection string</a> for the source organization.</li>
<li>When prompted to enter the the target connection string, supply a complete <a href="http://msdn.microsoft.com/en-us/library/gg695810.aspx">Dynamics CRM simplified connection string</a> for the target organization.</li>
<li>The tool will attempt to update existing team templates based on their ids. If any source records don't already exist in the target environment, they will be created (with the identical id).</li>
<li>Any failures will be reported by the tool. Errors will be encountered if the target schema doesn't match the source schema for the relevant entities.</li>
</ol>
<p>Here's a screenshot of the tool being executed:</p>
<p><img src="https://alexanderdevelopment.net/content/images/2014/12/team-mover-cli.PNG#img-thumbnail" alt="Console application for moving Dynamics CRM access team templates"></p>
<p>And the image below shows access teams in a source and target system after I ran the tool. The source system has two access team templates for entities that don't exist in the target system, so they were not created.</p>
<p><img src="https://alexanderdevelopment.net/content/images/2014/12/team-mover.PNG#img-thumbnail" alt="Console application for moving Dynamics CRM access team templates"></p>
<h4 id="theapproachindetail">The approach in detail</h4>
<p>Access team templates are just regular Dynamics CRM records, and they can be accessed through the Dynamics CRM organization web service like most other records. (You can see a list of the messages and methods available for 2013 <a href="http://msdn.microsoft.com/en-us/library/dn481595%28v=crm.6%29.aspx">here</a>). Because of this, all I needed to do was query a source CRM organization for access teams, and then loop through the results to recreate each one in the target organization.</p>
<p>At first I tried to retrieve the teamtemplate records using a RetrieveMultiple query for all attributes, but that resulted in a strange service fault involving the issystem attribute that looks like a bug in CRM. I then decided to use a FetchXML query instead. To make it easy on myself, I first make a metadata request to retrieve all the teamtemplate attributes, and then I dynamically build a FetchXML query for everything except the issystem field. That query then gets executed. The code for all the source organization operations is below:</p>
<pre><code>using (OrganizationService service = new OrganizationService(sourceConn))  
{  
 try  
 {  
 //attributes to exclude from the query  
 List&lt;string&gt; IgnoredAttributes = new List&lt;string&gt; { &quot;issystem&quot; };  
  
 Console.WriteLine(&quot;Retrieving entity metadata . . .&quot;);  
 RetrieveEntityRequest entityreq = new RetrieveEntityRequest  
 {  
 LogicalName = &quot;teamtemplate&quot;,  
 EntityFilters = Microsoft.Xrm.Sdk.Metadata.EntityFilters.Attributes  
 };  
 RetrieveEntityResponse entityres = (RetrieveEntityResponse)service.Execute(entityreq);  
 string fetchXml = &quot;&lt;fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'&gt;&quot;;  
 fetchXml += &quot;&lt;entity name='teamtemplate'&gt;&quot;;  
  
 foreach (AttributeMetadata amd in entityres.EntityMetadata.Attributes)  
 {  
 if (!IgnoredAttributes.Contains(amd.LogicalName))  
 {  
 fetchXml += &quot;&lt;attribute name='&quot; + amd.LogicalName + &quot;' /&gt;&quot;;  
 //Console.WriteLine(amd.LogicalName);  
 }  
 }  
 fetchXml += &quot;&lt;/entity&gt;&lt;/fetch&gt;&quot;;  
  
 Console.WriteLine(&quot;&quot;);  
 Console.WriteLine(&quot;Exporting data . . .&quot;);  
 exported = service.RetrieveMultiple(new FetchExpression(fetchXml));  
 }  
 catch (FaultException&lt;Microsoft.Xrm.Sdk.OrganizationServiceFault&gt; ex)  
 {  
 Console.WriteLine(&quot;Could not export data: {0}&quot;, ex.Message);  
 return;  
 }  
}
</code></pre>
<p>Once the teamtemplate records have been retrieved, they are then created in the target organization:</p>
<pre><code>using (OrganizationService service = new OrganizationService(targetConn))  
{  
 if (exported.Entities.Count &gt; 0)  
 {  
 foreach (Entity entity in exported.Entities)  
 {  
 try  
 {  
 //try to update first  
 try  
 {  
 service.Update(entity);  
 }  
 catch (FaultException&lt;Microsoft.Xrm.Sdk.OrganizationServiceFault&gt;)  
 {  
 //if update fails, then create  
 service.Create(entity);  
 }  
 }  
 catch (FaultException&lt;Microsoft.Xrm.Sdk.OrganizationServiceFault&gt; ex)  
 {  
 //if everything fails, return error  
 Console.WriteLine(&quot;Error: {0} - {1}&quot;, entity.Id, entity[&quot;teamtemplatename&quot;]);  
 }  
 }  
 }  
}
</code></pre>
<p>You'll note this code not only creates new records, but it also tries to update existing records, so if you have a teamtemplate that's changed, this will handle it if the record was created with the same GUID in the target system as in the source system.</p>
<p>What do you think about this approach? Would you have done anything differently?</p>
</div>]]></content:encoded></item><item><title><![CDATA[Diesel Xrm Service Wrapper Now on GitHub]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Last week I wrote a post called &quot;<a href="https://alexanderdevelopment.net/post/2013/07/31/introducing-the-diesel-xrm-service-wrapper">Introducing the Diesel Xrm Service Wrapper</a>,&quot; in which I presented a generic WCF wrapper for the Dynamics CRM Organization Service. Almost immediately I had several ideas about updates I wanted to make, so I've decided to host the project on GitHub.</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/08/04/diesel-xrm-service-wrapper-now-on-github/</link><guid isPermaLink="false">5a5837226636a30001b976d2</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[C#]]></category><category><![CDATA[web services]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[integration]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Mon, 05 Aug 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Last week I wrote a post called &quot;<a href="https://alexanderdevelopment.net/post/2013/07/31/introducing-the-diesel-xrm-service-wrapper">Introducing the Diesel Xrm Service Wrapper</a>,&quot; in which I presented a generic WCF wrapper for the Dynamics CRM Organization Service. Almost immediately I had several ideas about updates I wanted to make, so I've decided to host the project on GitHub. The project GitHub page is <a href="http://lucasalexander.github.io/DieselXrmWrapper/">here</a>, and you can find the code repository <a href="https://github.com/lucasalexander/DieselXrmWrapper">here</a>.</p>
<p>Here's a current list of enhancements I plan to add over the coming months:</p>
<ol start="2">
<li>Storing query FetchXml and related configuration data as custom entities in Dynamics CRM</li>
<li>Role-based authorization for individual queries</li>
<li>Varying impersonation settings per individual query</li>
<li>Updates</li>
<li>REST/JSON interfaces</li>
</ol>
<p>If you'd like to contribute or have any other interesting ideas, please drop me a line via my <a href="https://alexanderdevelopment.net/forms/contact-us">contact page</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Introducing the Diesel Xrm Service Wrapper]]></title><description><![CDATA[<div class="kg-card-markdown"><p>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,</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/07/30/introducing-the-diesel-xrm-service-wrapper/</link><guid isPermaLink="false">5a5837226636a30001b976da</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[C#]]></category><category><![CDATA[web services]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[integration]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Wed, 31 Jul 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>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!</p>
<p><img src="https://alexanderdevelopment.net/content/images/2013/07/diesel.jpg" alt="Diesel the Dynamics CRM Great Dane"></p>
<p>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.</p>
<p>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 &quot;query&quot; 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.</p>
<h4 id="initialconfiguration">Initial Configuration</h4>
<p>First, download the solution here: <a href="https://alexanderdevelopment.net/content/images/2013/07/DieselXrmSvcWrapper.zip">DieselXrmSvcWrapper.zip</a> <em>(Updated Aug. 5, 2013 - This project is now hosted on <a href="http://lucasalexander.github.io/DieselXrmWrapper/">GitHub</a>. The original solution file download link in this post has been left unchanged, however.)</em></p>
<p>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 &quot;Act On Behalf Of Another User.&quot; 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 &quot;UserName&quot; message clientCredentialType (that's WCF-speak for HTTP basic authentication over SSL).</p>
<h4 id="querydefinition">Query Definition</h4>
<p>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 &quot;query&quot; parameter maps queries to requests.</p>
<p>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:</p>
<pre><code>&lt;fetch version=&quot;1.0&quot; output-format=&quot;xml-platform&quot; mapping=&quot;logical&quot; distinct=&quot;false&quot;&gt;  
 &lt;entity name=&quot;contact&quot;&gt;  
 &lt;attribute name=&quot;fullname&quot; /&gt;  
 &lt;attribute name=&quot;contactid&quot; /&gt;  
 &lt;attribute name=&quot;ownerid&quot; /&gt;  
 &lt;attribute name=&quot;address1_stateorprovince&quot; /&gt;  
 &lt;attribute name=&quot;gendercode&quot; /&gt;  
 &lt;attribute name=&quot;createdon&quot; /&gt;  
 &lt;order attribute=&quot;fullname&quot; descending=&quot;false&quot; /&gt;  
 &lt;filter type=&quot;and&quot;&gt;  
 &lt;condition attribute=&quot;lastname&quot; operator=&quot;like&quot; value=&quot;{$lastnameletter}%&quot; /&gt;  
 &lt;/filter&gt;  
 &lt;/entity&gt;  
&lt;/fetch&gt; 
</code></pre>
<h4 id="samplesoapmessages">Sample SOAP Messages</h4>
<p>1<br>
Here's what the corresponding SOAP request method for the query above looks like:</p>
<pre><code>&lt;soapenv:Envelope   
 xmlns:soapenv=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;   
 xmlns:tem=&quot;http://tempuri.org/&quot;   
 xmlns:dies=&quot;http://schemas.datacontract.org/2004/07/DieselXrmSvcWrapper&quot;  
 xmlns:i=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&gt;  
 &lt;soapenv:Header/&gt;  
 &lt;soapenv:Body&gt;  
 &lt;tem:Retrieve&gt;  
 &lt;tem:query&gt;contacts&lt;/tem:query&gt;  
 &lt;tem:inputParameters&gt;  
 &lt;!--Zero or more repetitions:--&gt;  
 &lt;dies:ParameterItem&gt;  
 &lt;dies:Name&gt;lastnameletter&lt;/dies:Name&gt;  
 &lt;dies:Value i:type=&quot;b:string&quot; xmlns:b=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;C&lt;/dies:Value&gt;  
 &lt;/dies:ParameterItem&gt;  
 &lt;/tem:inputParameters&gt;  
 &lt;/tem:Retrieve&gt;  
 &lt;/soapenv:Body&gt;  
&lt;/soapenv:Envelope&gt;  
</code></pre>
<p>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.</p>
<p>The SOAP response for the request above is attached here: <a href="https://alexanderdevelopment.net/content/images/2013/07/soap-response.txt">soap-response.txt</a>.</p>
<h4 id="wrappingup">Wrapping Up</h4>
<p>Now that you understand how the solution behaves and how to configure it, here's an overview of the solution components:</p>
<ol>
<li>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 &quot;RetrieveQueries,&quot; but you can change it in the web.config file.</li>
<li>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.</li>
<li>SoapSvc.svc - This actually does the request/response processing.</li>
</ol>
<p>Once you have everything set up, you'll want to try it out, and I suggest using <a href="http://www.soapui.org">SoapUI</a>. 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 &quot;PasswordText,&quot; 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.</p>
<p><img src="https://alexanderdevelopment.net/content/images/2013/07/soap-ui.PNG#img-thumbnail" alt="SoapUI"></p>
<p>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.</p>
<p>Happy web service wrapping!</p>
</div>]]></content:encoded></item><item><title><![CDATA[A Data Snapshot Framework for Dynamics CRM]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Although Dynamics CRM offers several different ways to report on data stored in the system, there is no out-of-the-box mechanism for reporting on how data changes over time. That is to say, while you can easily report on how many active accounts are owned by a particular sales rep today,</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/07/23/data-snapshot-framework-for-dynamics-crm/</link><guid isPermaLink="false">5a5837226636a30001b976ca</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[C#]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[process automation]]></category><category><![CDATA[reporting]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Wed, 24 Jul 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Although Dynamics CRM offers several different ways to report on data stored in the system, there is no out-of-the-box mechanism for reporting on how data changes over time. That is to say, while you can easily report on how many active accounts are owned by a particular sales rep today, you can't report on how the number of active account compares to last week, last month or even just yesterday. Salesforce.com supports this type of historical summary reporting with a feature called &quot;analytic snapshots,&quot; but Dynamics CRM has typically required the use of an external data warehouse that is populated with summary data on a periodic basis. In this post, I will show how to set up a basic data snapshot framework inside Dynamics CRM that behaves like the analytic snapshot functionality of Salesforce.</p>
<p>Please note that this is not intended to replace a true enterprise data warehouse (EDW), but rather my solution is designed to complement existing CRM functionality by offering basic trend and summary data that can be used in reports and dashboard components. Using a separate data warehouse gives report writers a lot of power and flexibility, and I highly recommend using one to maximize your analytical capabilities.</p>
<h4 id="analyticsnapshotsexplained">Analytic Snapshots Explained</h4>
<p>According to the Salesforce help documentation:</p>
<blockquote>
<p>An analytic snapshot lets you report on historical data. Authorized users can save tabular or summary report results to fields on a custom object, then map those fields to corresponding fields on a target object. They can then schedule when to run the report to load the custom object's fields with the report's data. Analytic snapshots enable you to work with report data similarly to how you work with other records in Salesforce.</p>
</blockquote>
<p>Translated to Dynamics CRM-speak, basically the an administrator creates a new custom entity to hold the summary data, maps the fields from an existing report to the custom object and then schedules the snapshot to run daily, weekly or monthly. Once the summary data is captured in the custom object records, the data is available for reporting.</p>
<p>My solution achieves the same thing using a FetchXML query, a custom snapshot target entity, a custom snapshot definition entity, a workflow and a custom workflow activity. The custom snapshot definition entity, workflow and custom workflow activity constitute the snapshot processing framework, and then you will need to write a FetchXML query, create a snapshot definition record and define a custom target entity for each snapshot you want to set up. Let's take a closer look at how these pieces fit together.</p>
<h4 id="gettingstarted">Getting Started</h4>
<p>You can download my solution from the MSDN code gallery here: <a href="http://code.msdn.microsoft.com/Taking-Recurring-Data-d46ebf3f">Taking Scheduled Data Snapshots in Dynamics CRM</a>. Make sure to register the custom workflow assembly using the CRM SDK plug-in registration tool, and then import and publish the &quot;DataSnapshots&quot; CRM solution. The solution also contains a custom snapshot definition and target entity for this example.</p>
<p>If you would prefer to put together your own solution, skip ahead to the Snapshot Definition section and set up your own custom snapshot definition entity, workflow and custom workflow activity as explained. Once you're done, come back here to read about how to create the query and the target entity.</p>
<h4 id="fetchxmlquery">FetchXML Query</h4>
<p>Because Dynamics CRM doesn't think of reports the same way as Salesforce, I decided to use a FetchXML query as the data source for my snapshot solution. This query will be stored on the snapshot definition record, but you need to prepare it before you define your target entity so you can make sure to create all the right fields to store your snapshot data.</p>
<p>Here is a basic query that aggregates contact count and sum of annual income by owner and state:</p>
<pre><code>&lt;fetch mapping=&quot;logical&quot; aggregate=&quot;true&quot; distinct=&quot;false&quot;&gt;  
 &lt;entity name=&quot;contact&quot;&gt;  
 &lt;attribute name=&quot;fullname&quot; alias=&quot;fullname_count&quot; aggregate=&quot;count&quot;&gt;&lt;/attribute&gt;  
 &lt;attribute name=&quot;annualincome&quot; alias=&quot;annualincome_sum&quot; aggregate=&quot;sum&quot;&gt;&lt;/attribute&gt;  
 &lt;attribute name=&quot;address1_stateorprovince&quot; groupby=&quot;true&quot; alias=&quot;state_province&quot;&gt;&lt;/attribute&gt;  
 &lt;attribute name=&quot;ownerid&quot; groupby=&quot;true&quot; alias=&quot;owner&quot;&gt;&lt;/attribute&gt;  
 &lt;/entity&gt;  
&lt;/fetch&gt;  
</code></pre>
<h4 id="customsnapshottargetentity">Custom Snapshot Target Entity</h4>
<p>After you figure out the data you want to capture, you have to create a custom entity to store it. For the query I showed above, I have created a custom entity called &quot;Snapshot - Contacts by State&quot; (la_snapshotcontactsbystate). You can name your entities anything you want, but I suggest some sort of common prefix to keep them organized. I have also chosen organization ownership, but user/team ownership shouldn't cause any problems.</p>
<p><img src="https://alexanderdevelopment.net/content/images/2013/07/snapshot-target-main.PNG#img-thumbnail" alt="Snapshot target entity"></p>
<p>On this entity, I have created custom fields as shown in the following screenshot:</p>
<p><img src="https://alexanderdevelopment.net/content/images/2013/07/snapshot-target-custom-fields.PNG#img-thumbnail" alt="Snapshot target custom fields"></p>
<p>Obviously your custom fields will vary depending on the data your query returns. One critically important thing to remember is that you must use the exact same data types for your custom fields as are returned by the query. My custom workflow activity code is relatively unforgiving, so even something like trying to store an integer value in a decimal field, which would not have resulted in data loss, caused errors in my testing.</p>
<h4 id="snapshotdefinition">Snapshot Definition</h4>
<p>Once you have your target entity defined, you are now ready to create a snapshot definition record to store the query, field mappings and frequency/scheduling details. This shows a snapshot definition that corresponds to the query and target that I explained above.</p>
<p><img src="https://alexanderdevelopment.net/content/images/2013/07/snapshot-definition.PNG#img-thumbnail" alt="Snapshot definition"></p>
<ol>
<li>The target entity name is the system name for the target entity, in this case la_snapshotcontactsbystate.</li>
<li>The next run date field is when the snapshot will execute. The workflow that executes the snapshot runs according to a timeout whenever this value changes, and it sets the next run date in the future according to the value of the frequency field (add one day/seven days/one month) at the end of the process, thus triggering the next run. If want to enable different frequency choices, you can update the picklist options and the next run date update logic in the workflow.</li>
<li>The query field is your FetchXML query.</li>
<li>The field mappings are in the format of source&gt;target, each on a separate line. You can use an alternate separator character than &quot;&gt;&quot; if you update the custom workflow activity code and redeploy the assembly.</li>
</ol>
<h4 id="customworkflowactivity">Custom Workflow Activity</h4>
<p>The custom workflow activity behaves a lot like the custom workflow activity I created for my <a href="https://alexanderdevelopment.net/post/2013/05/19/Scheduling-recurring-Dynamics-CRM-workflows-with-FetchXML">Scheduling recurring Dynamics CRM workflows with FetchXML</a> post. It takes a FetchXML query as an input parameter, executes the query and then loops through the results to do some additional work. For the data snapshots, we also need to know the name of the target entity and the field mappings. Here are the relevant input parameters:</p>
<pre><code>[Input(&quot;FetchXML query&quot;)]  
public InArgument FetchXMLQuery { get; set; }  
  
[Input(&quot;Snapshot mappings&quot;)]  
public InArgument SnapshotMappings { get; set; }  
  
[Input(&quot;Target entity&quot;)]  
public InArgument TargetEntity { get; set; }  
</code></pre>
<p>In the interest of saving space, I'm not posting the entire Execute method, but here is the section that does the query/loop/create bits:</p>
<pre><code>try  
{  
 //get the source-&gt;target field mappings from the input parameters  
 string mappingsText = SnapshotMappings.Get(executionContext);  
  
 //split up the lines into an array  
 string[] mappingLines = mappingsText.Split(Environment.NewLine.ToCharArray());  
  
 //create a dictionary object to hold the mappings  
 Dictionary&lt;string, string&gt; mappingDictionary = new Dictionary&lt;string,string&gt;();  
  
 //for each line in the array, split it on the &quot;&gt;&quot; character and store the source-&gt;target as a key-value pair  
 foreach(string s in mappingLines)  
 {  
 try   
 {  
 string targetfield = s.Split(&quot;&gt;&quot;.ToCharArray())[1];  
 string sourcefield = s.Split(&quot;&gt;&quot;.ToCharArray())[0];  
 tracingService.Trace(&quot;line: &quot; + s + &quot; source: &quot; + sourcefield + &quot; target: &quot; + targetfield);  
 mappingDictionary.Add(sourcefield, targetfield);  
 }  
 catch(Exception ex)  
 {  
 throw new InvalidPluginExecutionException(&quot;Error parsing source-&gt;target mappings.&quot;);  
 }  
 }  
  
 //get the target entity name from the input parameters  
 string targetEntityType = TargetEntity.Get(executionContext);  
  
 //execute the fetchxml query and loop through the results  
 EntityCollection recordsToProcess = service.RetrieveMultiple(new FetchExpression(FetchXMLQuery.Get(executionContext)));  
 recordsToProcess.Entities.ToList().ForEach(a =&gt;  
 {  
 tracingService.Trace(&quot;instantiating new entity of type: &quot; + targetEntityType);  
 Entity targetRecord = new Entity(targetEntityType);  
   
 //loop through the mapping key-value pairs  
 foreach (string key in mappingDictionary.Keys)  
 {  
 //check to see if attribute exists in this particular result  
 //fetchxml results don't return fields with null values  
 if (a.Contains(key))  
 {  
 //if the result field is an aliasedvalue, we need to handle it differently than non-aliasedvalue types  
 if (a[key].GetType().FullName.ToUpperInvariant().EndsWith(&quot;ALIASEDVALUE&quot;))  
 {  
 //cast it to aliasedvalue  
 var resultfield = (AliasedValue)a[key];  
  
 //set the target field to the casted resultfield value  
 targetRecord[mappingDictionary[key]] = resultfield.Value;  
  
 //trace just in case  
 tracingService.Trace(&quot;new source column [&quot; + key + &quot;]: destination [&quot; + mappingDictionary[key] + &quot;]: &quot; + (resultfield.Value).ToString());  
 }  
 else  
 {  
 //set the target field to the resultfield  
 //target field needs to be of EXACT same type as result field  
 //for example, this code doesn't work if you try to store an integer in a decimal field  
 targetRecord[mappingDictionary[key]] = a[key];  
  
 //trace just in case  
 tracingService.Trace(&quot;new source column [&quot; + key + &quot;]: destination [&quot; + mappingDictionary[key] + &quot;]: &quot; + (a[key]).ToString());  
 }  
 }  
 }  
 try  
 {  
 //create the record  
 service.Create(targetRecord);  
 }  
 catch (FaultException e)  
 {  
 //catch orgservice faults  
 tracingService.Trace(&quot;Exception: {0}&quot;, e.ToString());  
  
 // Handle the exception.  
 throw new InvalidPluginExecutionException(&quot;Could not create snapshot record.&quot;);  
 }  
 catch (Exception ex)  
 {  
 //catch anything else  
 throw new InvalidPluginExecutionException(&quot;Could not create snapshot record.&quot;);  
 }  
  
 });  
}
</code></pre>
<h4 id="thesnapshottingworkflow">The Snapshotting Workflow</h4>
<p>Finally, I created a workflow process called &quot;Take Snapshot.&quot; As explained above, it runs whenever the next run date field on a snapshot definition record changes. Here's the business logic it executes at a high level:</p>
<ol>
<li>Timeout until snapshot definition's next run date</li>
<li>Execute the Take Snapshot custom workflow activity with input parameters taken from the snapshot definition query, mapping and target entity fields</li>
<li>Update the next run date based on the frequency</li>
</ol>
<h4 id="snapshotresults">Snapshot Results</h4>
<p>Once you set everything up and the workflow executes, you'll then be able to query snapshot data. Here's a screenshot of an advanced find view with the snapshot from this example.</p>
<p><img src="https://alexanderdevelopment.net/content/images/2013/07/snapshot-results.PNG#img-thumbnail" alt="Snapshot results"></p>
<p>Happy data snapshotting!</p>
</div>]]></content:encoded></item><item><title><![CDATA[Creating a dynamic dialog launcher menu for Dynamics CRM (FetchXML style)]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Last month I wrote a <a href="https://alexanderdevelopment.net/post/2013/05/17/Creating-a-dynamic-dialog-launcher-menu-for-Dynamics-CRM">post</a> about how to create a web resource dialog &quot;launcher&quot; that you can embed in a CRM form (both classic and updated modes) with JavaScript and an OData query. In today's post, I will show how to do the same thing using a</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/06/02/creating-a-dynamic-dialog-launcher-menu-for-dynamics-crm-fetchxml-style-2/</link><guid isPermaLink="false">5a5837226636a30001b97755</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[jQuery]]></category><category><![CDATA[process automation]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Mon, 03 Jun 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Last month I wrote a <a href="https://alexanderdevelopment.net/post/2013/05/17/Creating-a-dynamic-dialog-launcher-menu-for-Dynamics-CRM">post</a> about how to create a web resource dialog &quot;launcher&quot; that you can embed in a CRM form (both classic and updated modes) with JavaScript and an OData query. In today's post, I will show how to do the same thing using a FetchXML query. There are four changes you need to make to the web resource from the previous post.</p>
<p><strong>ClientGlobalContext.js.aspx</strong></p>
<p>First, because we're working with FetchXML, you need to add a reference to ClientGlobalContext.js.aspx JavaScript to your page head.</p>
<p><strong>Add the buildFetchRequest function</strong></p>
<p>You need to add a function to build a full SOAP request from a FetchXML query. This is the same buildFetchRequest function I have used in previous <a href="https://alexanderdevelopment.net/?tag=/FetchXML">FetchXML-related posts</a>.</p>
<pre><code>function buildFetchRequest(fetch) {  
/// &lt;summary&gt;  
/// builds a properly formatted FetchXML request  
/// based on Paul Way's blog post &quot;Execute Fetch from JavaScript in CRM 2011&quot;  
/// http://blog.customereffective.com/blog/2011/05/execute-fetch-from-javascript-in-crm-2011.html  
/// &lt;/summary&gt;  
var request = &quot;&lt;s:Envelope xmlns:s=\&quot;http://schemas.xmlsoap.org/soap/envelope/\&quot;&gt;&quot;;  
request += &quot;&lt;s:Body&gt;&quot;;   
  
request += '&lt;Execute xmlns=&quot;http://schemas.microsoft.com/xrm/2011/Contracts/Services&quot;&gt;' +   
'&lt;request i:type=&quot;b:RetrieveMultipleRequest&quot; ' +   
' xmlns:b=&quot;http://schemas.microsoft.com/xrm/2011/Contracts&quot; ' +   
' xmlns:i=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&gt;' +   
'&lt;b:Parameters xmlns:c=&quot;http://schemas.datacontract.org/2004/07/System.Collections.Generic&quot;&gt;' +   
'&lt;b:KeyValuePairOfstringanyType&gt;' +   
'&lt;c:key&gt;Query&lt;/c:key&gt;' +   
'&lt;c:value i:type=&quot;b:FetchExpression&quot;&gt;' +   
'&lt;b:Query&gt;';  
  
request += CrmEncodeDecode.CrmXmlEncode(fetch);   
  
request += '&lt;/b:Query&gt;' +   
'&lt;/c:value&gt;' +   
'&lt;/b:KeyValuePairOfstringanyType&gt;' +   
'&lt;/b:Parameters&gt;' +   
'&lt;b:RequestId i:nil=&quot;true&quot;/&gt;' +   
'&lt;b:RequestName&gt;RetrieveMultiple&lt;/b:RequestName&gt;' +   
'&lt;/request&gt;' +   
'&lt;/Execute&gt;';   
  
request += '&lt;/s:Body&gt;&lt;/s:Envelope&gt;';   
return request;  
}  
</code></pre>
<p><strong>Update the getDialogList function</strong></p>
<p>You also need to update the getDialogList function to build and execute a FetchXML query instead of an OData query. Here is the updated function:</p>
<pre><code>//function to retrieve the dialogs  
function getDialogList() {  
var dialogname = dataObj[&quot;dialogname&quot;];  
var entitytypename = dataObj[&quot;entitytypename&quot;];   
  
//only execute query if the record already exists  
if((recordId != null) &amp;&amp; (recordId != '')) {  
  
//no point if entitytypename is provided  
if((entitytypename != null) &amp;&amp; (entitytypename != ''))  
{  
//path to CRM root  
var server = window.location.protocol + &quot;//&quot; + window.location.host;  
  
//full path to CRM organization service - you may need to modify this depending on your particular situation  
var path = server + &quot;/XRMServices/2011/Organization.svc/web&quot;;  
var fetchQuery = '&lt;fetch version=&quot;1.0&quot; output-format=&quot;xml-platform&quot; mapping=&quot;logical&quot; distinct=&quot;false&quot;&gt;';  
fetchQuery += '&lt;entity name=&quot;workflow&quot;&gt;';  
fetchQuery += '&lt;attribute name=&quot;workflowid&quot; /&gt;';  
fetchQuery += '&lt;attribute name=&quot;name&quot; /&gt;';  
fetchQuery += '&lt;attribute name=&quot;category&quot; /&gt;';  
fetchQuery += '&lt;attribute name=&quot;primaryentity&quot; /&gt;';  
fetchQuery += '&lt;attribute name=&quot;type&quot; /&gt;';  
fetchQuery += '&lt;attribute name=&quot;description&quot; /&gt;';  
fetchQuery += '&lt;order attribute=&quot;name&quot; descending=&quot;false&quot; /&gt;';  
fetchQuery += '&lt;filter type=&quot;and&quot;&gt;';  
fetchQuery += '&lt;condition attribute=&quot;name&quot; operator=&quot;like&quot; value=&quot;'+dialogname+'%&quot; /&gt;';  
fetchQuery += '&lt;condition attribute=&quot;type&quot; operator=&quot;eq&quot; value=&quot;1&quot; /&gt;';  
fetchQuery += '&lt;condition attribute=&quot;category&quot; operator=&quot;eq&quot; value=&quot;1&quot; /&gt;';  
fetchQuery += '&lt;condition attribute=&quot;primaryentityname&quot; operator=&quot;eq&quot; value=&quot;'+entitytypename+'&quot; /&gt;';  
fetchQuery += '&lt;/filter&gt;';  
fetchQuery += '&lt;/entity&gt;';  
fetchQuery += '&lt;/fetch&gt;';  
  
var fetchRequest = buildFetchRequest(fetchQuery);  
  
$.ajax({  
type: &quot;POST&quot;,  
dataType: &quot;xml&quot;,  
contentType: &quot;text/xml; charset=utf-8&quot;,  
processData: false,  
url: path,  
data: fetchRequest,  
//complete: function(xhr, status) {  
// console.log(xhr.responseText);  
//},  
beforeSend: function( xhr ){  
xhr.setRequestHeader(  
&quot;SOAPAction&quot;,  
&quot;http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute&quot;  
); //without the SOAPAction header, CRM will return a 500 error  
}  
}).done(function(data) {  
//if successful, pass returned xml to the display function  
generateLauncherMenu(data);  
}).fail(function(jqXHR, textStatus, errorThrown ) {  
//if unsuccessful, generate an error alert message  
alert( &quot;Request failed: &quot; + textStatus + &quot;\n&quot; + errorThrown );  
});  
}  
}  
</code></pre>
<p><strong>Update the generateLauncherMenu function</strong></p>
<p>Finally, you need to update the generateLauncherMenu function to accept an XML input parameter and parse/process accordingly. Here is an updated version that, as in my previous example, generates buttons to launch the dialogs:</p>
<pre><code>//callback function to parse the response and build the menu output  
function generateLauncherMenu(xml) {  
$(xml).find(&quot;a\\:Entity&quot;).each(function() {  
var workflowid, primaryentity, name, paramString;  
//inner loop  
$(this).find(&quot;a\\:KeyValuePairOfstringanyType&quot;).each(function() {  
var xmlElement = $(this);  
var key = xmlElement.find(&quot;b\\:key&quot;).text();  
var value = xmlElement.find(&quot;b\\:value&quot;).text();  
switch(key) {  
case &quot;workflowid&quot;:  
workflowid = value;  
break;  
case &quot;primaryentity&quot;:  
primaryentity = value;  
break;  
case &quot;name&quot;:  
name = value;  
break;  
}  
paramString = &quot;\&quot;&quot; + workflowid + &quot;\&quot;,\&quot;&quot; + primaryentity + &quot;\&quot;,\&quot;&quot; +recordId + &quot;\&quot;&quot;;  
});  
$('#launchDiv').append( &quot;&lt;button onclick='openDialog(&quot;+paramString+&quot;)'&gt;Launch &quot; + name + &quot;&lt;/button&gt;&amp;nbsp;&amp;nbsp;&quot; );  
});  
}
</code></pre>
<p><strong>Wrapping up</strong></p>
<p>Once those four changes are made, this web resource will behave exactly like the OData version.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Scheduling recurring Dynamics CRM workflows with FetchXML]]></title><description><![CDATA[<div class="kg-card-markdown"><p>In today's post I will show how to set up a recurring process in Dynamics CRM that executes a FetchXML query to return a set of records and then starts a workflow for each of those records without requiring any external processes or tools. This is a generalized approach to</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/05/18/scheduling-recurring-dynamics-crm-workflows-with-fetchxml/</link><guid isPermaLink="false">5a5837216636a30001b976b7</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[C#]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[process automation]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Sun, 19 May 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>In today's post I will show how to set up a recurring process in Dynamics CRM that executes a FetchXML query to return a set of records and then starts a workflow for each of those records without requiring any external processes or tools. This is a generalized approach to solving a class of problems that includes the following scenarios:</p>
<ol>
<li>The birthday greetings problem: How can you, on a daily basis, send an e-mail to every contact with a birthday = today (where the date value for today is obviously different every day)?</li>
<li>The monthly update problem: How can you, on a monthly basis, generate an activity for every account with status reason = X (where it's important that the process only runs on a certain day of the month based on status reason values as of that exact date)?</li>
</ol>
<p>While you could accomplish both of these using workflows with timeouts, I think that would be a bad approach. In the case of the birthday greetings problem, I don't like to have workflows in a waiting state for an entire year. For the monthly update problem, a timeout-based approach could get extremely complex. Another more general issue with waiting workflows is that business rules can change, so if you have thousands of workflows in a waiting state and the business owner says she wants to update the process to do X instead of Y, it can be a serious pain to cancel the waiting workflows, update the definition and then restart them. (And yes, I speak from personal, painful experience.)</p>
<p>My solution requires three things:</p>
<ol>
<li>A custom workflow activity (StartScheduledWorkflows) that can execute a supplied FetchXML query and initiate the workflow for each retrieved record.</li>
<li>A custom entity (Scheduled Process) to hold the FetchXML query and scheduling details.</li>
<li>A workflow (Scheduled Workflow Runner) to run the StartScheduledWorkflows activity on a recurring schedule.</li>
</ol>
<p><strong>How it works</strong></p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/05/scheduled_workflow_process.png#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/05/scheduled_workflow_process.png#img-thumbnail" alt=""></a></p>
<p>A Scheduled Process record is created, which starts a corresponding Scheduled Workflow Runner workflow in a timeout state. When the next run date == the current time, the Scheduled Workflow Runner workflow initiates the StartScheduledWorkflows activity with the FetchXML query and workflow lookup from the Scheduled Process record. The StartScheduledWorkflows activity advances the next run date of the Scheduled Process record, and then it executes the FetchXML, loops through the results and starts the workflow from the lookup for each record. A newly started Scheduled Workflow Runner workflow then waits for the next run date to start the process again.</p>
<p><strong>Creating the custom workflow activity</strong></p>
<p>The custom workflow activity is easy to implement. As described above, a FetchXML query and a workflow lookup are supplied as input parameters, and then the workflow is started for each record returned by the FetchXML query. Here's the code for my StartScheduledWorkflows class.</p>
<pre><code>public sealed class StartScheduledWorkflows : CodeActivity  
{  
[Input(&quot;FetchXML query&quot;)]  
public InArgument&lt;String&gt; FetchXMLQuery { get; set; }  
  
[Input(&quot;Workflow&quot;)]  
[ReferenceTarget(&quot;workflow&quot;)]  
public InArgument&lt;EntityReference&gt; Workflow { get; set; }  
  
//name of your custom workflow activity for tracing/error logging  
private string _activityName = &quot;RunDailyProcess&quot;;  
  
/// &lt;summary&gt;  
/// Executes the workflow activity.  
/// &lt;/summary&gt;  
/// &lt;param name=&quot;executionContext&quot;&gt;The execution context.&lt;/param&gt;  
protected override void Execute(CodeActivityContext executionContext)  
{  
// Create the tracing service  
ITracingService tracingService = executionContext.GetExtension&lt;ITracingService&gt;();  
  
if (tracingService == null)  
{  
throw new InvalidPluginExecutionException(&quot;Failed to retrieve tracing service.&quot;);  
}  
  
tracingService.Trace(&quot;Entered &quot; + _activityName + &quot;.Execute(), Activity Instance Id: {0}, Workflow Instance Id: {1}&quot;,  
executionContext.ActivityInstanceId,  
executionContext.WorkflowInstanceId);  
  
// Create the context  
IWorkflowContext context = executionContext.GetExtension&lt;IWorkflowContext&gt;();  
  
if (context == null)  
{  
throw new InvalidPluginExecutionException(&quot;Failed to retrieve workflow context.&quot;);  
}  
  
tracingService.Trace(_activityName + &quot;.Execute(), Correlation Id: {0}, Initiating User: {1}&quot;,  
context.CorrelationId,  
context.InitiatingUserId);  
  
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension&lt;IOrganizationServiceFactory&gt;();  
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);  
  
try  
{  
EntityCollection recordsToProcess = service.RetrieveMultiple(new FetchExpression(FetchXMLQuery.Get(executionContext)));  
recordsToProcess.Entities.ToList().ForEach(a =&gt;  
{  
ExecuteWorkflowRequest request = new ExecuteWorkflowRequest  
{  
EntityId = a.Id,  
WorkflowId = (Workflow.Get(executionContext)).Id  
};  
  
service.Execute(request); //run the workflow  
});  
}  
catch (FaultException&lt;OrganizationServiceFault&gt; e)  
{  
tracingService.Trace(&quot;Exception: {0}&quot;, e.ToString());  
  
// Handle the exception.  
throw;  
}  
catch (Exception e)  
{  
tracingService.Trace(&quot;Exception: {0}&quot;, e.ToString());  
throw;  
}  
  
tracingService.Trace(&quot;Exiting &quot; + _activityName + &quot;.Execute(), Correlation Id: {0}&quot;, context.CorrelationId);  
}  
}
</code></pre>
<p><strong>Creating the custom entity</strong></p>
<p>To run the scheduled processes, we will need a custom entity called Scheduled Process to hold at least four pieces of data:</p>
<ol>
<li>The FetchXML query to execute</li>
<li>The workflow that will be started for the retrieved records</li>
<li>The next run date/time on which the process should be executed</li>
<li>How often the job should be run (frequency)</li>
</ol>
<p>In addition to those, I also have fields to hold the relevant entity name and the last run date. Neither of these are required for my approach to work, but they make managing the processes easier if you have a lot. Here's a screenshot of a Scheduled Process record:</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/05/scheduled_process_screenshot.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/05/scheduled_process_screenshot.PNG#img-thumbnail" alt=""></a></p>
<p><strong>Creating the scheduling workflow</strong></p>
<p>Finally we need a Scheduled Workflow Runner workflow that will manage the execution of each scheduled process record. It should look like the following:</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/05/scheduled_workflow_runner.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/05/scheduled_workflow_runner.PNG#img-thumbnail" alt=""></a></p>
<p>The workflow runs when the next run date value of Scheduled Process changes. Once we reach the next run date for a Scheduled Process, the workflow updates the last run date to the process execution time and the next run date to the process execution based on the Scheduled Process frequency. There are three &quot;loop&quot; conditional branches to handle this, so if the frequency is &quot;hourly,&quot; then the next run date is set to the process execution time + one hour. You can modify your frequency values on the the Scheduled Process record, but you'll have to add a separate conditional check in the workflow for each one. Alternatively you could use another custom workflow activity to intelligently handle different frequency values, but I wanted to keep the coding to a minimum for this example.</p>
<p>Because next run date is based on when the Scheduled Workflow Runner actually executes, your next run date times may end up skewing over time. That is, if you start a Scheduled Process running at 6:00 a.m., by the fifth iteration, you might end up with 11:05 a.m. instead of 11:00 a.m. For this reason, I suggest you have a process in place to occasionally check these values and reset them as needed. Potential automated solutions include using another Scheduled Process to fix the time skew, or custom code in a plug-in or custom workflow activity to re-baseline the time. If anyone has any other suggestions, please share them in the comments.</p>
<p>After the updates are made, the workflow executes the StartScheduledWorkflows custom workflow activity to start the workflows for the relevant records, and you're done.</p>
<p><strong>Putting it all together</strong></p>
<p>I've uploaded the custom workflow activity code and an export of my unmanaged CRM solution to the <a href="http://code.msdn.microsoft.com/Executing-Dynamics-CRM-93f3b52a">MSDN developer samples code gallery</a> (direct download link <a href="http://code.msdn.microsoft.com/Executing-Dynamics-CRM-93f3b52a/file/82316/3/Executing%20Dynamics%20CRM%20workflows%20based%20on%20a%20FetchXML%20query.zip">here</a>). The solution export includes a built assembly with the custom workflow activity ready for registration in your CRM system.</p>
<p>Happy workflow scheduling!</p>
</div>]]></content:encoded></item><item><title><![CDATA[Displaying Dynamics CRM FetchXML results in ASPX with XSLT]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Last week I wrote a <a href="https://alexanderdevelopment.net/post/2013/02/21/Accessing-raw-SOAP-requests-responses-from-Dynamics-CRM-web-services-in-C.aspx">post</a> that showed how to retrive the raw SOAP response from a Dynamics CRM query in C#, but I didn't show how to do anything useful with it. In today's post I will show a practical example of how to execute a FetchXML request against</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/02/26/displaying-dynamics-crm-fetchxml-results-xslt/</link><guid isPermaLink="false">5a5837226636a30001b9771f</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[C#]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[ASP.Net]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Wed, 27 Feb 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Last week I wrote a <a href="https://alexanderdevelopment.net/post/2013/02/21/Accessing-raw-SOAP-requests-responses-from-Dynamics-CRM-web-services-in-C.aspx">post</a> that showed how to retrive the raw SOAP response from a Dynamics CRM query in C#, but I didn't show how to do anything useful with it. In today's post I will show a practical example of how to execute a FetchXML request against a Dynamics CRM instance, capture the raw SOAP response and transform it with XSLT for display in an ASPX page. For demonstration purposes, I will be using the same query and XSL as I used in my <a href="https://alexanderdevelopment.net/post/2013/02/11/Displaying-FetchXML-results-with-XSLT-on-the-client-side-in-a-Dynamics-CRM-2011-web-resource.aspx">&quot;Displaying FetchXML results with XSLT on the client side in a Dynamics CRM 2011 web resource&quot;</a> post.</p>
<p>In this example I am using a WSDL-based proxy instead of the CRM SDK, but all of the code I am sharing can be easily modified to work with the SDK instead.</p>
<p>My ASPX page has five controls:</p>
<ol>
<li>xmlTextBox textbox to input the FetchXML query</li>
<li>xslTextBox textbox to input the XSL for the transformation</li>
<li>executeButton button to retrieve and transform the data</li>
<li>resultsTextBox textbox to show the SOAP response</li>
<li>resultsLiteral literal to show the transformed data</li>
</ol>
<p>When the executeButton button is clicked, the following steps take place:</p>
<ol>
<li>Set up a WCF client connection to the CRM OrganizationService (with client message inspector as described in my last post)</li>
<li>Retrieve the results for the supplied FetchXML query</li>
<li>Show the SOAP response</li>
<li>Transform the SOAP response using the supplied XSL</li>
<li>Show the transformed results</li>
</ol>
<p>Here's the code:</p>
<pre><code>/// &lt;summary&gt;  
/// executes retrieve and transform functionality  
/// &lt;/summary&gt;  
/// &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;  
/// &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;  
protected void executeButton_Click(object sender, EventArgs e)  
{  
OrganizationServiceClient client = SetupClient();  
string results = RetrieveData(this.xmlTextBox.Text, client);  
  
string xsl = this.xslTextBox.Text;  
this.resultsTextBox.Text = results;  
this.resultsLiteral.Text = DoTransform(results, xsl);  
}  
  
/// &lt;summary&gt;  
/// instantiates an OrganizationServiceClient object for the username/password/organization service specified as constants  
/// &lt;/summary&gt;  
/// &lt;returns&gt;&lt;/returns&gt;  
private OrganizationServiceClient SetupClient()  
{  
ClientCredentials credentials = new ClientCredentials();  
credentials.UserName.UserName = UserName; //UserName is a constant  
credentials.UserName.Password = UserPassword; //UserPassword is a constant  
  
OrganizationServiceClient client = new OrganizationServiceClient(&quot;CustomBinding_IOrganizationService&quot;,  
new EndpointAddress(OrganizationServiceUrl)); //OrganizationServiceUrl is a constant  
client.ClientCredentials.UserName.UserName = credentials.UserName.UserName;  
client.ClientCredentials.UserName.Password = credentials.UserName.Password;  
return client;  
}  
  
/// &lt;summary&gt;  
/// executes a fetchxml query with a given org service client and returns the SOAP response as a string  
/// &lt;/summary&gt;  
/// &lt;param name=&quot;fetchXml&quot;&gt;query&lt;/param&gt;  
/// &lt;param name=&quot;client&quot;&gt;client&lt;/param&gt;  
/// &lt;returns&gt;response&lt;/returns&gt;  
string RetrieveData(string fetchXml, OrganizationServiceClient client)  
{  
string response = &quot;&quot;;  
  
//set up a client message inspector for the query  
//see http://alexanderdevelopment.net/post/2013/02/21/Accessing-raw-SOAP-requests-responses-from-Dynamics-CRM-web-services-in-C.aspx  
MyInspector inspector = new MyInspector();  
client.Endpoint.Behaviors.Add(inspector);  
  
//build the fetchxml  
FetchExpression fetch = new FetchExpression();  
fetch.Query = fetchXml;  
EntityCollection entities = client.RetrieveMultiple(fetch);  
  
//if there is a captured response  
if (inspector.receivedMessages.Count == 1)  
{  
response = inspector.receivedMessages[0];  
}  
  
//return it  
return response;  
}  
  
/// &lt;summary&gt;  
/// transforms supplied results xml with supplied xsl  
/// &lt;/summary&gt;  
/// &lt;param name=&quot;results&quot;&gt;input xml&lt;/param&gt;  
/// &lt;param name=&quot;xsl&quot;&gt;xsl style sheet&lt;/param&gt;  
/// &lt;returns&gt;transformed output&lt;/returns&gt;  
string DoTransform(string results, string xsl)  
{  
//create an xmldocument from the input xml  
System.Xml.XmlDocument xmlDoc = new XmlDocument();  
xmlDoc.LoadXml(results);  
  
//create an xmldocument from the input xsl  
System.Xml.XmlDocument xslDoc = new XmlDocument();  
xslDoc.LoadXml(xsl);  
  
//load a compiled xsl transform object from the xsl document  
XslCompiledTransform transform = new XslCompiledTransform();  
transform.Load(xslDoc);  
  
//prepare stringwriter and xmlwriter get string output from transformation  
StringWriter sw = new StringWriter();  
XmlWriter xwriter = XmlWriter.Create(sw);  
  
//execute the transformation  
transform.Transform(xmlDoc, xwriter);  
  
//return the output  
string output = sw.ToString();  
return output;  
}
</code></pre>
<p>My .aspx and .aspx.cs files are attached here for reference.</p>
<ol>
<li><a href="https://alexanderdevelopment.net/content/images/2013/02/DisplayXml.aspx.txt">DisplayXml.aspx (3.16 kb)</a></li>
<li><a href="https://alexanderdevelopment.net/content/images/2013/02/DisplayXml.aspx.cs.txt">DisplayXml.aspx.cs (4.95 kb)</a></li>
</ol>
</div>]]></content:encoded></item><item><title><![CDATA[Displaying FetchXML results with XSLT on the client side in a Dynamics CRM 2011 web resource]]></title><description><![CDATA[<div class="kg-card-markdown"><p>A few weeks back, I wrote a post that showed <a href="https://alexanderdevelopment.net/post/2013/01/20/FetchXML-JQuery-in-a-Dynamics-CRM-2011-web-resource">how to retrieve and display FetchXML using jQuery in a Dynamics CRM web resource</a>. In that example, I used jQuery's each() method to iterate through each result and append them to an HTML element on the page. Using each() is</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/02/10/displaying-fetchxml-results-with-xslt-on-the-client-side-in-a-dynamics-crm-2011-web-resource/</link><guid isPermaLink="false">5a5837226636a30001b97726</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[jQuery]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Mon, 11 Feb 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>A few weeks back, I wrote a post that showed <a href="https://alexanderdevelopment.net/post/2013/01/20/FetchXML-JQuery-in-a-Dynamics-CRM-2011-web-resource">how to retrieve and display FetchXML using jQuery in a Dynamics CRM web resource</a>. In that example, I used jQuery's each() method to iterate through each result and append them to an HTML element on the page. Using each() is a good approach if you need to actually do something with each row, but if you just want to display data, XSLT is a much easier way to do it. In this post, I will show how to use client-side XSLT to format a FetchXML response for display.</p>
<p><strong>Fetching the data</strong></p>
<p>To display data, obviously we need to retrieve some data first. Using the approach from my earlier post, we will use the following FetchXML query to return a list of contacts:</p>
<pre><code>&lt;fetch version=&quot;1.0&quot; output-format=&quot;xml-platform&quot; mapping=&quot;logical&quot; distinct=&quot;false&quot;&gt;  
&lt;entity name=&quot;contact&quot;&gt;  
&lt;attribute name=&quot;fullname&quot; /&gt;  
&lt;attribute name=&quot;contactid&quot; /&gt;  
&lt;attribute name=&quot;ownerid&quot; /&gt;  
&lt;attribute name=&quot;gendercode&quot; /&gt;  
&lt;attribute name=&quot;address1_stateorprovince&quot; /&gt;  
&lt;attribute name=&quot;createdon&quot; /&gt;  
&lt;/entity&gt;  
&lt;/fetch&gt;
</code></pre>
<p>When I execute this query, I get the output in the attached contacts.xml file: <a href="https://alexanderdevelopment.net/content/images/2013/02/contacts_raw.xml">contacts_raw.xml (50.68 kb)</a>.</p>
<p><strong>Designing the display format</strong></p>
<p>It we are going to use XSLT to format XML data, we will need an XSL style sheet. A detailed discussion of XSL is beyond the scope of this post, but I will point out a couple of things about my style sheet:</p>
<p>First, I use a template to match the root node, and then I loop through each entity with this for-each element:</p>
<p><em>&lt;xsl:for-each select=&quot;//a:Entities/a:Entity&quot;&gt;</em></p>
<p>The &quot;//a:Entities&quot; tells it to match an a:Entities element with any ancestors so you don't have to match all the way to the top-level s:Envelope ancestor.</p>
<p>Second, FetchXML represents an attribute (or formattedvalue) as an element with one &quot;key&quot; child and one &quot;value&quot; child. The &quot;key&quot; child is the attribute name, and the &quot;value&quot; is, obviously, the value. Thus, from each entity, I select the attribute and formattedvalue data to display using elements like this:</p>
<p><em>&lt;xsl:value-of select=&quot;a:Attributes/a:KeyValuePairOfstringanyType[b:key='fullname']/b:value&quot; /&gt;</em></p>
<p>What that means is &quot;select the 'b:value' element that has an 'a:KeyValuePairOfstringanyType' that has a 'b:key' element equal to 'fullname.'&quot; Alternatively, you can think abou it as &quot;select the 'b:value' element that has a sibling 'b:key' element equal to 'fullname.'&quot;</p>
<p>Here is the complete XSL style sheet: <a href="https://alexanderdevelopment.net/content/images/2013/02/contacts.xsl">contacts.xsl (1.35 kb)</a>.</p>
<p>Once you have your XSL style sheet ready, upload it to your CRM instance as a web resource of type &quot;Style Sheet (XSL).&quot; Make sure you remember the relative path of the new resource. In my case it is &quot;new_contacts.xsl.&quot;</p>
<p><strong>Applying the transformation</strong></p>
<p>Now that we have some FetchXML results and an XSL style sheet, all that's left to do is to transform the returned FetchXML and display it on the page. To do that, I have made a few modifications to my earlier FetchXML retrieval logic. Because jQuery retrieves things by default asynchronously, I start with retrieving the XSL document, then I use a callback function to retrieve the FetchXML results and finally I use a callback function to do the transformation. In the interest of not cluttering my code with global variables, I pass everything I need through the chain of callbacks. For example, my XSL retrieval method takes the FetchXML request as a parameter just so it can pass it to its callback. Then that callback takes the XSL document so that its callback has the XSL.</p>
<p>The code to do the apply and display the transformation is below:</p>
<pre><code>function processData(xml, xsl) {  
/// &lt;summary&gt;  
/// transforms xml with a supplied xsl style sheet and appends the output to a div on the page  
/// &lt;/summary&gt;  
  
//instantiate a variable to hold the transformed xml  
var resultDocument = &quot;&quot;;  
resultDocument = TransformToHtmlText(xml, xsl);  
alert(&quot;Output started&quot;);  
$(&quot;#outputdiv&quot;).append(resultDocument);  
  
alert(&quot;Output complete&quot;);  
}  
  
function TransformToHtmlText(xmlDoc, xsltDoc) {  
/// &lt;summary&gt;  
/// Transforms a XML document to a HTML string by using a XSLT document  
/// 1. Use type XSLTProcessor, if browser (FF, Safari, Chrome etc) supports it  
/// 2. Use function [transformNode] on the XmlDocument, if browser (IE6, IE7, IE8) supports it  
/// 3. Use function transform on the XsltProcessor used for IE9 (which doesn't support [transformNode] any more)   
/// 4. Throws an error, when both types are not supported  
/// taken from &quot;How to fix: DOMParser.TransformNode not supported in IE9&quot;  
/// http://www.roelvanlisdonk.nl/?p=2113  
/// &lt;/summary&gt;  
// 1.  
if (typeof (XSLTProcessor) != &quot;undefined&quot;) {  
var xsltProcessor = new XSLTProcessor();  
xsltProcessor.importStylesheet(xsltDoc);  
var xmlFragment = xsltProcessor.transformToFragment(xmlDoc, document);  
return xmlFragment;  
}  
// 2.  
if (typeof (xmlDoc.transformNode) != &quot;undefined&quot;) {  
return xmlDoc.transformNode(xsltDoc);  
}  
else {  
  
try {  
// 3  
if (window.ActiveXObject) {  
var xslt = new ActiveXObject(&quot;Msxml2.XSLTemplate&quot;);  
var xslDoc = new ActiveXObject(&quot;Msxml2.FreeThreadedDOMDocument&quot;);  
xslDoc.loadXML(xsltDoc.xml);  
xslt.style sheet = xslDoc;  
var xslProc = xslt.createProcessor();  
xslProc.input = xmlDoc;  
xslProc.transform();  
  
return xslProc.output;  
}  
}  
catch (e) {  
// 4  
alert(&quot;The type [XSLTProcessor] and the function [XmlDocument.transformNode] are not supported by this browser, can't transform XML document to HTML string!&quot;);  
return null;  
}  
  
}  
}
</code></pre>
<p>Two points to note:</p>
<ol>
<li>The processData method doesn't apply the transformation itself. It passes the XML and XSL to another method called TransformToHtmlText.</li>
<li>The TransformToHtmlText method allows us to easily handle differences in the way that different browsers (or even different versions of the same browser) handle XML. For more information take a look at <a href="http://www.roelvanlisdonk.nl/?p=2113">http://www.roelvanlisdonk.nl/?p=2113</a> and <a href="http://stackoverflow.com/questions/12149410/object-doesnt-support-property-or-method-transformnode-in-internet-explorer-1">http://stackoverflow.com/questions/12149410/object-doesnt-support-property-or-method-transformnode-in-internet-explorer-1</a>.</li>
</ol>
<p><strong>Trying it out</strong></p>
<p>Here is a complete web page with the code for you to download and try out in your own CRM instance: <a href="https://alexanderdevelopment.net/content/images/2013/02/fetchxml_xslt.htm">fetchxml_xslt.htm (7.02 kb)</a>. Just upload it as you would any other web resource, publish and open. At that point you will be presented with a screen that looks like this:</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/02/fetch_start.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/02/fetch_start.PNG#img-thumbnail" alt="The FetchXML / jQuery / XSLT example page"></a></p>
<p>Either leave the pre-populated FetchXML in the textarea or supply your own. Once you click the &quot;fetch and process&quot; button, you will start to see some output and a couple of status alert windows before the output finally displays. The end result should look something like this:</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/02/fetch_complete.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/02/fetch_complete.PNG#img-thumbnail" alt="The FetchXML / jQuery / XSLT example page showing output"></a></p>
</div>]]></content:encoded></item><item><title><![CDATA[Better line charts in Dynamics CRM 2011 - part II]]></title><description><![CDATA[<div class="kg-card-markdown"><p>In <a href="https://alexanderdevelopment.net/post/2013/01/24/Better-Line-Charts-in-Dynamics-CRM-2011-part-I.aspx">part I</a> of this series, I showed how to query Microsoft Dynamics CRM for aggregate data using FetchXML and then pass the results to <a href="http://www.flotcharts.org">Flot</a> to generate a line chart. In this second part, I will expand on that to show how to query for and chart multi-series data.</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/01/26/better-line-charts-in-dynamics-crm-2011-part-ii/</link><guid isPermaLink="false">5a5837216636a30001b97697</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[data visualizations]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[jQuery]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Sun, 27 Jan 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>In <a href="https://alexanderdevelopment.net/post/2013/01/24/Better-Line-Charts-in-Dynamics-CRM-2011-part-I.aspx">part I</a> of this series, I showed how to query Microsoft Dynamics CRM for aggregate data using FetchXML and then pass the results to <a href="http://www.flotcharts.org">Flot</a> to generate a line chart. In this second part, I will expand on that to show how to query for and chart multi-series data. For my example today, I will be creating a chart that shows the number of contacts created by date and state (address, not statecode). In my CRM instance, I have created a set of contacts using characters from Cohen brothers movies. (Please, hold your &quot;Big Lebowski&quot; quotes.)</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/01/contacts.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/01/contacts.PNG#img-thumbnail" alt="Contacts"></a></p>
<p><strong>Changes to the previous approach</strong></p>
<p>There are three main things we have to do differently here than before:</p>
<ol>
<li>Update the FetchXML query to include an additional group-by field</li>
<li>Update the results parser to handle the additional group-by field</li>
<li>Send Flot an array of data series instead of just one</li>
</ol>
<p>In addition to that, I have improved the original code in two more ways:</p>
<ol>
<li>Fill in missing date values with 0 so the shape of the line better reflects reality</li>
<li>Shade weekend days in gray on the chart grid to help break up the weeks and highlight areas in which we might logically expect no activity to occur</li>
</ol>
<p><strong>Updated FetchXML</strong></p>
<p>Changing the FetchXML query is easy. We just have to add the address1_stateorprovince field:</p>
<pre><code>&lt;fetch distinct='false' mapping='logical' aggregate='true'&gt;  
&lt;entity name='contact'&gt;  
&lt;attribute name='fullname' alias='plotValue' aggregate='count' /&gt;  
&lt;attribute name='address1_stateorprovince' groupby='true' alias='seriesLabel' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='day' alias='day' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='month' alias='month' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='year' alias='year' /&gt;  
&lt;/entity&gt;  
&lt;/fetch&gt;
</code></pre>
<p>The field we will use to create the data series is aliased as &quot;seriesLabel&quot; so we can have as generic a results parsing method as possible.</p>
<p><strong>Updated results parser</strong></p>
<p>The manner in which I wrote the getKeyValPairs function in part I won't return the seriesLabel field as part of the return object because only the numeric values come back in the a:FormattedValues element. The seriesLabel field is available via the a:Attributes element, so this required a minor change to my XML find logic. If you have downloaded my previous charting sample, you should be able to update the getKeyValPairs function in it with the newer version here without any issues.</p>
<pre><code>function getKeyValPairs(entity, valuefield) {  
/// &lt;summary&gt;  
/// extracts an aggregate value and grouping components from a FetchXML response entity element and returns them in an array  
/// &lt;/summary&gt;  
var outputArray = new Array();  
  
//first, get the aggregate value using its alias (&quot;plotValue&quot; in the original example)  
var pointValue = parseFloat(entity.find(&quot;a\\:KeyValuePairOfstringstring&quot;).filter(function() {  
return $(this).find('b\\:key').text() == valuefield;  
}).find(&quot;b\\:value&quot;).text().replace(/,/g,''));  
var groupingArray = [];  
  
//second, get the values for the group-by fields  
//unlike previous example, this uses the a:KeyValuePairOfstringanyType element   
//so we go down an extra &quot;value&quot; level when populating the value variable  
entity.find(&quot;a\\:KeyValuePairOfstringanyType&quot;).each(function() {  
return $(this).find('b\\:key').text() != valuefield;  
}).each(function() {  
var xmlElement = $(this);  
var key = xmlElement.find(&quot;b\\:key&quot;).text();  
var value = xmlElement.find(&quot;b\\:value&quot;).find(&quot;a\\:Value&quot;).text();  
var groupingText = '&quot;' + key + '&quot;:&quot;' + value + '&quot;';  
groupingArray.push(groupingText);  
});  
var stringToEval = groupingArray.join();  
var dateFields = eval(&quot;({&quot;+stringToEval+&quot;})&quot;);  
outputArray.push(pointValue);  
outputArray.push(dateFields);  
  
return outputArray;  
}
</code></pre>
<p><strong>Sending Flot the data</strong></p>
<p>Flot expects data to be passed as an array of objects like this:</p>
<pre><code>{   
label: &quot;Series Label&quot;,   
data: [[x1,y1],[x2,y2]...   
}
</code></pre>
<p>In our example, we would have a separate object for each state's data. To build the array of data objects, we do the following:</p>
<ol>
<li>Get a list of unique series labels (states)</li>
<li>Create a holding array for each series' data points</li>
<li>Assign each data point to its correct series in the holding array</li>
<li>Build the data array Flot expects from the holding array</li>
</ol>
<p>As part of building the data array for Flot, we also do some date manipulation to fill in missing dates with 0 values.</p>
<p>Here are the functions that do all of this:</p>
<pre><code>function processData(xml) {  
/// &lt;summary&gt;  
/// charts data returned in a FetchXML response using Flot  
/// &lt;/summary&gt;  
  
alert(&quot;Charting started&quot;);  
  
//array to hold series labels  
var seriesList = [];  
  
//array to hold the series data before we get it ready for flot  
var pointSeries = [];  
  
//array to hold data to pass to flot  
var dataSeries = [];  
  
//array to hold all each unique date in our data set   
//this is so we can show dates with no data between the start and finish dates as 0  
var dateArray = [];  
  
//loop through xml and extract data from each &quot;entity&quot; element  
$(&quot;#chartdiv&quot;).append(&quot;Starting XML parsing . . . &lt;br /&gt;&quot;);  
$(xml).find(&quot;a\\:Entity&quot;).each(function() {  
//pass the element to a function that extracts the aggregate value and the &quot;group by&quot; values  
//&quot;plotValue&quot; is the FetchXML alias for the data we want to display  
var pointData = getKeyValPairs($(this),&quot;plotValue&quot;);   
  
//for each unique series label value  
if(seriesList.indexOf(pointData[1].seriesLabel) == -1) {  
//add label to array of labels  
seriesList.push(pointData[1].seriesLabel);  
  
//instantiate a new array to hold data for this series  
pointSeries.push(new Array());  
}  
  
//Flot requires datetimes to be passed as timestamp values  
var pointDate = new Date(pointData[1].year, pointData[1].month-1, pointData[1].day);  
var timestamp = pointDate.getTime();  
  
//for each unique date value  
if(dateArray.indexOf(timestamp) == -1) {  
//add date timestamp to array of dates  
dateArray.push(timestamp);  
}  
  
//get the index of the series to which this particular value corresponds  
var seriesNumber = seriesList.indexOf(pointData[1].seriesLabel);  
  
//add this particular data value to the correct array in the point series array  
pointSeries[seriesNumber].push([timestamp, pointData[0]]);  
  
});  
  
//sort the unique dates so we can find the min and max dates later  
dateArray.sort(function(a,b){return a-b;});  
  
//we have a function that fills in missing dates with 0 values  
//so to make sure all series have the same set of data, we will add a dummy date to both ends of the range with 0 values  
//after we have &quot;filled out&quot; any missing values in the series, we will remove the dummy dates  
//get milliseconds per day so we can just add/subtract the value of the &quot;day&quot; variable later  
var minute = 1000 * 60;  
var hour = minute * 60;  
var day = hour * 24;  
  
//for each series  
for(var i=0; i&lt;seriesList.length; i++) {  
//the label we pass to Flot is the value from the series label array  
var seriesLabel = seriesList[i];  
  
//get a time series data variable from the correct array in the pointseries aray  
var tsData = pointSeries[i];  
  
//add a day with a 0 value to the beginning of the series  
tsData.push([dateArray[0]-day,0]);  
  
//add a day with a 0 value to the end of the series  
tsData.push([dateArray[dateArray.length-1]+day,0]);  
  
//sort the data points by date  
tsData.sort(function(a,b){return a[0]-b[0];});  
  
//fill in missing dates with 0-value points  
tsData = newDataArray(tsData);  
  
//remove the first &quot;dummy&quot; date  
tsData.shift();  
  
//remove the last &quot;dummy&quot; date  
tsData.pop();  
  
//create a new object to represent this series  
var seriesObj = new Object();  
  
//set a label property  
seriesObj.label = seriesLabel;  
  
//set a data property  
seriesObj.data = tsData;  
  
//add this object to the dataseries array that will be passed to Flot  
dataSeries.push(seriesObj);  
}  
  
//plot the data with some display options  
//see examples and API documentation at http://www.flotcharts.org/  
$.plot($(&quot;#chartdiv&quot;),   
dataSeries, {   
series: {  
lines: { show: true },  
points: { show: true }  
},   
grid: {   
hoverable: true ,  
markings: weekendAreas //calls the weekendAreas function to shade weekend days in gray  
},  
xaxis: {   
tickLength: 5,  
mode: &quot;time&quot;,  
timeformat: &quot;%m/%d/%y&quot;  
},  
yaxis: {  
tickDecimals: 0,  
min: 0  
}  
}  
);  
  
alert(&quot;Charting complete&quot;);  
}  
  
//this function is used to fill in the missing date values with 0 values  
//taken from http://stackoverflow.com/questions/14522667/how-to-configure-flot-to-draw-missing-time-series-on-y-axis-at-point-zero  
function newDataArray(data) {  
var startDay = data[0][0],  
newData = [data[0]];  
  
for (i = 1; i &lt; data.length; i++) {  
var diff = dateDiff(data[i - 1][0], data[i][0]);  
var startDate = new Date(data[i - 1][0]);  
if (diff &gt; 1) {  
for (j = 0; j &lt; diff - 1; j++) {  
var fillDate = new Date(startDate).setDate(startDate.getDate() + (j + 1));  
newData.push([fillDate, 0]);  
}  
}  
newData.push(data[i]);  
}  
return newData;  
}  
  
  
/* helper function to find date differences*/  
function dateDiff(d1, d2) {  
return Math.floor((d2 - d1) / (1000 * 60 * 60 * 24));  
}
</code></pre>
<p><strong>Format for the weekends</strong></p>
<p>The final difference from part I is calling a custom function to format the weekends on the chart. This is done in this part of the processData function above:</p>
<pre><code>grid: {   
hoverable: true ,  
markings: weekendAreas //calls the weekendAreas function to shade weekend days in gray  
},
</code></pre>
<p>The weekendAreas function:</p>
<pre><code>//helper for returning the weekends in a period  
//taken from http://www.flotcharts.org/flot/examples/visitors/index.html  
function weekendAreas(axes) {  
var markings = [];  
var d = new Date(axes.xaxis.min);  
// go to the first Saturday  
d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 1) % 7))  
d.setUTCSeconds(0);  
d.setUTCMinutes(0);  
d.setUTCHours(0);  
var i = d.getTime();  
do {  
// when we don't set yaxis, the rectangle automatically  
// extends to infinity upwards and downwards  
markings.push({ xaxis: { from: i, to: i + 2 * 24 * 60 * 60 * 1000 } });  
i += 7 * 24 * 60 * 60 * 1000;  
} while (i &lt; axes.xaxis.max);  
  
return markings;  
}
</code></pre>
<p><strong>Trying it out</strong></p>
<p>Here is a complete web page with the code for you to download and try out in your own CRM instance <a href="https://alexanderdevelopment.net/content/images/2013/01/chart_example2.htm">chart_example2.htm (12.34 kb)</a>. Just upload it as you would any other web resource, publish and open.</p>
<p>When I run it in my CRM instance, this chart is generated.</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/01/contact_state_chart.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/01/contact_state_chart.PNG#img-thumbnail" alt="Generated chart"></a></p>
<p>As you can see, the chart gets a little busy, and it's hard to differentiate between the different series where they overlap, but there's a lot more you can do with Flot formatting options to make it look better. Also, I haven't covered everything Flot can do, so I encourage you to look at the Flot <a href="http://www.flotcharts.org/flot/examples/">examples page</a> to see some other possibilities like bar charts, stacked charts, panning/zooming, etc.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Better line charts in Dynamics CRM 2011 - part I]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Earlier this week I posted an <a href="https://alexanderdevelopment.net/post/2013/01/21/FetchXML-JQuery-in-a-Dynamics-CRM-2011-web-resource.aspx">entry</a> about using FetchXML and JQuery in a Dynamics CRM 2011 web resource. The reason I first started looking at those two together was that I wanted to see if I could generate better looking line charts than are available out of the box</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/01/23/better-line-charts-in-dynamics-crm-2011-part-i/</link><guid isPermaLink="false">5a5837216636a30001b97671</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[data visualizations]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[jQuery]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Thu, 24 Jan 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Earlier this week I posted an <a href="https://alexanderdevelopment.net/post/2013/01/21/FetchXML-JQuery-in-a-Dynamics-CRM-2011-web-resource.aspx">entry</a> about using FetchXML and JQuery in a Dynamics CRM 2011 web resource. The reason I first started looking at those two together was that I wanted to see if I could generate better looking line charts than are available out of the box (spoiler alert: I did). In this post I will show how to combine FetchXML and JQuery with the <a href="http://www.flotcharts.org/">Flot</a> plotting library to produce line charts from CRM data aggregations.</p>
<p>In my career, one of the data visualizations I have encountered the most is to plot some value over unit time. For example, we can try to measure an agent's productivity by counting the number of phone calls per day. Because of the way Dynamics CRM stores data, if we restrict our queries to its database instead of a data warehouse, generally we can report on actions taken per unit time, but we can't report on how things change over time. We can say Agent X created 100 phone call records last week, but we can't tell how many overdue phone call records Agent X had in the queue yesterday. In my example here, I will show how to plot number of contacts created per day.</p>
<p><strong>Top of the page stuff</strong></p>
<p>Charting with Flot requires jQuery, Flot (obviously) and Excanvas in Internet Explorer. Here is how I pull those libraries in from CDNs, but if your CRM instance is accessed over a LAN, you should host them locally.</p>
<pre><code>&lt;!--[if lte IE 8]&gt;&lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot; src=&quot;https://cdnjs.cloudflare.com/ajax/libs/flot/0.7/excanvas.min.js&quot;&gt;&lt;/script&gt;&lt;![endif]--&gt;  
&lt;script src=&quot;https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.0.min.js&quot;&gt;&lt;/script&gt;  
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/flot/0.7/jquery.flot.min.js&quot;&gt;&lt;/script&gt;
</code></pre>
<p>Also, Flot doesn't work so well in Internet Explorer quirks mode, so make sure you set the page to display in standards mode by declaring an HTML doctype like so in the first line: <!DOCTYPE html></p>
<p><strong>Writing the query</strong></p>
<p>As I explained previously, if you want to query aggregate data from inside JavaScript, you have to use FetchXML. While researching this topic, the examples I found weren't necessarily the clearest, but MSDN has a good overview <a href="http://msdn.microsoft.com/en-us/library/gg309565">here</a>.</p>
<p>Once you get the hang of the FetchXML syntax, if you can write your query in SQL group-by syntax, it shouldn't be too difficult to translate it to FetchXML. Here is the query we will use to count contacts by their createdon date:</p>
<pre><code>&lt;fetch distinct='false' mapping='logical' aggregate='true'&gt;  
&lt;entity name='contact'&gt;  
&lt;attribute name='fullname' alias='plotValue' aggregate='count' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='day' alias='day' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='month' alias='month' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='year' alias='year' /&gt;  
&lt;/entity&gt;  
&lt;/fetch&gt;
</code></pre>
<p>We have a single data field aliased as plotValue that is equivalent to SQL's count(fullname) as plotValue, and then there are three groupby fields that are based on the createdon field. They have each been given an alias that corresponds to the specific datepart.</p>
<p><strong>Executing the query</strong></p>
<p>To execute the FetchXML and retrieve the results, we will use the same basic technique I showed in my previous post.</p>
<ol>
<li>Get FetchXML query from a textarea field.</li>
<li>Build a SOAP message.</li>
<li>Send the SOAP message to CRM and register a callback function to process the data.</li>
</ol>
<p>To do this, we will use the same function executeFetchCommand, buildFetchRequest and sendQuery methods from my previous post. We will be using a different processData method, though the name will stay the same.</p>
<p><strong>Charting the data</strong></p>
<p>Once the data is returned by CRM, we can generate the chart. To do that, we will do the following:</p>
<ol start="2">
<li>Loop through XML to extract count for each date.</li>
<li>Convert the count and date values to an array of X and Y values for Flot to plot.</li>
<li>Call the Flot plotting method.</li>
<li>Bind an event to our chart to display tooltip messages that show the X and Y values when the user mouses over a specific point.</li>
</ol>
<p>First, our new processData callback function looks like this:</p>
<pre><code>function processData(xml) {  
/// &lt;summary&gt;  
/// charts data returned in a FetchXML response using Flot  
/// &lt;/summary&gt;  
  
alert(&quot;Charting started&quot;);  
  
//create a label for the chart points  
var yLabel = &quot;Contacts created&quot;;  
  
//create an array to hold the plot data  
var series1 = [];  
  
//loop through xml and extract data from each &quot;entity&quot; element  
$(&quot;#chartdiv&quot;).append(&quot;Starting XML parsing . . . &lt;br /&gt;&quot;);  
$(xml).find(&quot;a\\:Entity&quot;).each(function() {  
//pass the element to a function that extracts the aggregate value and the &quot;group by&quot; values  
//&quot;plotValue&quot; is the FetchXML alias for the data we want to display  
var pointData = getKeyValPairs($(this),&quot;plotValue&quot;);   
  
//Flot requires datetimes to be passed as timestamp values  
var dateString = (pointData[1].year + &quot;-&quot; + pointData[1].month + &quot;-&quot; + pointData[1].day).replace(/,/g,'');  
var timestamp = new Date(pointData[1].year.replace(/,/g,''), parseInt(pointData[1].month)-1, pointData[1].day).getTime();  
  
//add x (timestamp) and y (aggregate data value) values to the data series array  
series1.push([timestamp, pointData[0]]);  
});  
  
//sort series array by date - Flot plots in order, so line can look wrong if we don't do this  
series1.sort(function(a,b){return a[0]-b[0];});  
  
//plot the data with some display options  
//see examples and API documentation at http://www.flotcharts.org/  
$.plot($(&quot;#chartdiv&quot;),   
[ { data: series1, label: yLabel} ], {   
series: {  
lines: { show: true },  
points: { show: true }  
},   
grid: { hoverable: true },  
xaxis: {   
tickSize: [1, &quot;day&quot;],  
mode: &quot;time&quot;,  
timeformat: &quot;%m/%d/%y&quot;  
}  
}  
);  
  
alert(&quot;Charting complete&quot;);  
}
</code></pre>
<p>In this method first we loop through the data and pass each element to a getKeyValPairs helper function to extract the necessary fields. It returns an array with the Y value to plot as element 0 and a JSON object containing all other fields as element 1. It looks like this:</p>
<pre><code>function getKeyValPairs(entity, valuefield) {  
/// &lt;summary&gt;  
/// extracts an aggregate value and grouping components from a FetchXML response entity element and returns them in an array  
/// &lt;/summary&gt;  
var outputArray = new Array();  
  
//first get the aggregate value using its alias (&quot;plotValue&quot; in the original example)  
var pointValue = parseFloat(entity.find(&quot;a\\:KeyValuePairOfstringstring&quot;).filter(function() {  
return $(this).find('b\\:key').text() == valuefield;  
}).find(&quot;b\\:value&quot;).text().replace(/,/g,''));  
var groupingArray = [];  
entity.find(&quot;a\\:KeyValuePairOfstringstring&quot;).filter(function() {  
return $(this).find('b\\:key').text() != valuefield;  
}).each(function() {  
var xmlElement = $(this);  
var key = xmlElement.find(&quot;b\\:key&quot;).text();  
var value = xmlElement.find(&quot;b\\:value&quot;).text();  
var groupingText = '&quot;' + key + '&quot;:&quot;' + value + '&quot;';  
groupingArray.push(groupingText);  
});  
var stringToEval = groupingArray.join();  
var dateFields = eval(&quot;({&quot;+stringToEval+&quot;})&quot;);  
outputArray.push(pointValue);  
outputArray.push(dateFields);  
  
return outputArray;  
}
</code></pre>
<p>Once the data fields are returned by they getKeyValPairs method, the processData function creates a timestamp from the supplied month, day and year fields (Flot requires timestamps to plot by datetime), and then adds the timestamp and count to an array.</p>
<p>After the loop is complete, we sort the array by date to make sure the line will be plotted along our points in the correct order. Finally we call the Flot plot function with the data array and some pre-determined options. There are a lot of cool configuration options you can specify for Flot plots, but explaining them is beyond the scope of this point. Please take a look at the Flot <a href="http://people.iola.dk/olau/flot/examples/">examples</a> page for more.</p>
<p>Finally we need some code to do the tooltip display. First we have a generic showTooltip method that will be executed when the mouse moves over a data point. You can customize the style to your liking.</p>
<pre><code>function showTooltip(x, y, contents) {  
/// &lt;summary&gt;  
/// function to show tooltip when user mouses over data points  
/// &lt;/summary&gt;  
$('&lt;div id=&quot;tooltip&quot;&gt;' + contents + '&lt;/div&gt;').css( {  
position: 'absolute',  
display: 'none',  
top: y + 5,  
left: x + 5,  
border: '1px solid #fdd',  
padding: '2px',  
'background-color': '#fee',  
opacity: 0.80  
}).appendTo(&quot;body&quot;).fadeIn(200);  
}
</code></pre>
<p>Then we have code that binds a function to the chart plothover event so that the showTooltip method gets executed at the right time with the right data:</p>
<pre><code>//bind a function to execute the showTooltip function at the appropriate time  
var previousPoint = null;  
$(&quot;#chartdiv&quot;).bind(&quot;plothover&quot;, function (event, pos, item) {  
$(&quot;#x&quot;).text(pos.x.toFixed(2));  
$(&quot;#y&quot;).text(pos.y.toFixed(2));  
  
if (item) {  
if (previousPoint != item.dataIndex) {  
previousPoint = item.dataIndex;  
  
$(&quot;#tooltip&quot;).remove();  
var date = new Date(item.datapoint[0]);  
var x = item.datapoint[0].toFixed(2),  
y = item.datapoint[1];  
  
//call showTooltip with the timestamp converted back to mm/dd/yyyy format  
showTooltip(item.pageX, item.pageY,  
item.series.label + &quot; on &quot; + (parseInt(date.getMonth()+1)) + &quot;/&quot; + date.getDate() + &quot;/&quot; + date.getFullYear() + &quot; = &quot; + y);  
}  
}  
else {  
$(&quot;#tooltip&quot;).remove();  
previousPoint = null;   
}  
  
}); 
</code></pre>
<p><strong>Trying it out</strong></p>
<p>Here is a complete web page with the code for you to download and try out in your own CRM instance <a href="https://alexanderdevelopment.net/content/images/2013/01/chart_example.htm">chart_example.htm (8.30 kb)</a>. Just upload it as you would any other web resource, publish and open. At that point you will be presented with a screen that looks like this:</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/01/chart_fetch_start.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/01/chart_fetch_start.PNG#img-thumbnail" alt="The FetchXML / JQuery / Flot example page"></a></p>
<p>Either leave the pre-populated FetchXML in the textarea or supply your own that does a count by month, day and year. As long as it returns those three group-by fields and a Y value aliased as &quot;plotValue,&quot; it should work. Once you click the &quot;fetch and process&quot; button, you will start to see some output and a couple of status alert windows before the output finally displays. The end result should look like this:</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/01/chart_fetch_complete.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/01/chart_fetch_complete.PNG#img-thumbnail" alt="The FetchXML / JQuery / Flot example page"></a></p>
<p>Of course this chart is actually not that exciting, but once you take a closer look at how you can format the line chart output with Flot, you'll see there are all sorts of interesting things you can do. You can also embed the charts in dashboards as a replacement for the existing Dynamics CRM line chart controls. Stay tuned for my next post when I show how to generate multi-series charts.</p>
</div>]]></content:encoded></item><item><title><![CDATA[FetchXML + jQuery in a Dynamics CRM 2011 web resource]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Over the weekend I started looking at a hobby project that involved querying and working with aggregate data from Dynamics CRM 2011 inside a hosted web resource using jQuery. Initially had I planned to use the OData/REST endpoint since that is much sexier than SOAP lately, but after a</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/01/20/fetchxml-jquery-in-a-dynamics-crm-2011-web-resource/</link><guid isPermaLink="false">5a5837216636a30001b976b0</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[jQuery]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Mon, 21 Jan 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Over the weekend I started looking at a hobby project that involved querying and working with aggregate data from Dynamics CRM 2011 inside a hosted web resource using jQuery. Initially had I planned to use the OData/REST endpoint since that is much sexier than SOAP lately, but after a quick web search I realized that OData doesn't support &quot;group by&quot; queries, so that left me looking at FetchXML. As I mentioned in a post last month, I've generally avoided working with FetchXML, so I wasn't even sure where to get started to use it inside JavaScript. After another quick web search, I came across a great post on the Customer Effective blog called <a href="http://blog.customereffective.com/blog/2011/05/execute-fetch-from-javascript-in-crm-2011.html">Execute Fetch from JavaScript in CRM 2011</a>. That post shows a custom FetchUtil.js library that does three things:</p>
<ol>
<li>Create a properly formatted SOAP request for a FetchXML query</li>
<li>Execute the request using the XMLHttpRequest object</li>
<li>Return the XML response to the browser</li>
</ol>
<p>Using this original post to point me in the right direction, I combined the logic for creating the SOAP request with new jQuery code to handle the request and response. Here's how it works:</p>
<p><strong>Getting the FetchXML</strong></p>
<p>First we need to get the FetchXML to execute. For the purpose of this example, suppose we allow a user to execute ad-hoc FetchXML queries, so we need a method to read FetchXML from a textarea on a web page and then start processing. This method will be executed when a button is pushed:</p>
<pre><code>function executeFetchCommand() {   
/// &lt;summary&gt;  
/// reads user-supplied FetchXML contained in the txtFetch textarea and starts processing  
/// &lt;/summary&gt;  
  
//generate the SOAP envelope  
var fetchRequest = buildFetchRequest($(&quot;textarea#txtFetch&quot;).val());  
  
//send the request to CRM  
sendQuery(fetchRequest);  
}
</code></pre>
<p>The buildFetchRequest and sendQuery methods are described in the following sections.</p>
<p><strong>Generating the request</strong></p>
<p>First we need to generate the SOAP envelope from a FetchXML query. This method takes the query as an input parameter, properly encodes it and wraps it inside the envelope.</p>
<pre><code>function buildFetchRequest(fetch) {  
/// &lt;summary&gt;  
/// builds a properly formatted FetchXML request  
/// based on Paul Way's blog post &quot;Execute Fetch from JavaScript in CRM 2011&quot;  
/// http://blog.customereffective.com/blog/2011/05/execute-fetch-from-javascript-in-crm-2011.html  
/// &lt;/summary&gt;  
var request = &quot;&lt;s:Envelope xmlns:s=\&quot;http://schemas.xmlsoap.org/soap/envelope/\&quot;&gt;&quot;;  
request += &quot;&lt;s:Body&gt;&quot;;   
  
request += '&lt;Execute xmlns=&quot;http://schemas.microsoft.com/xrm/2011/Contracts/Services&quot;&gt;' +   
'&lt;request i:type=&quot;b:RetrieveMultipleRequest&quot; ' +   
' xmlns:b=&quot;http://schemas.microsoft.com/xrm/2011/Contracts&quot; ' +   
' xmlns:i=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&gt;' +   
'&lt;b:Parameters xmlns:c=&quot;http://schemas.datacontract.org/2004/07/System.Collections.Generic&quot;&gt;' +   
'&lt;b:KeyValuePairOfstringanyType&gt;' +   
'&lt;c:key&gt;Query&lt;/c:key&gt;' +   
'&lt;c:value i:type=&quot;b:FetchExpression&quot;&gt;' +   
'&lt;b:Query&gt;';  
  
request += CrmEncodeDecode.CrmXmlEncode(fetch);   
  
request += '&lt;/b:Query&gt;' +   
'&lt;/c:value&gt;' +   
'&lt;/b:KeyValuePairOfstringanyType&gt;' +   
'&lt;/b:Parameters&gt;' +   
'&lt;b:RequestId i:nil=&quot;true&quot;/&gt;' +   
'&lt;b:RequestName&gt;RetrieveMultiple&lt;/b:RequestName&gt;' +   
'&lt;/request&gt;' +   
'&lt;/Execute&gt;';   
  
request += '&lt;/s:Body&gt;&lt;/s:Envelope&gt;';   
return request;  
}
</code></pre>
<p><strong>Executing the query</strong></p>
<p>Once you have the SOAP envelope ready, you need to send the request to your CRM server. This method takes the SOAP envelope generated in the previous step, makes an asynchronous call to the CRM 2011 organization service using the jQuery ajax method and registers a callback function to process the returned results. (It also writes some status info to an output region of a web page to make it easier for you to follow the code execution.)</p>
<pre><code>function sendQuery(fetchRequest) {  
/// &lt;summary&gt;  
/// uses jQuery ajax method to executes a FetchXML query and register a callback function  
/// &lt;/summary&gt;  
  
//path to CRM root  
var server = window.location.protocol + &quot;//&quot; + window.location.host;  
  
//full path to CRM organization service - you may need to modify this depending on your particular situation  
var path = server + &quot;/XRMServices/2011/Organization.svc/web&quot;;  
  
$(&quot;#outputdiv&quot;).append(&quot;Starting ajax request . . . &lt;br /&gt;&quot;);  
$.ajax({  
type: &quot;POST&quot;,  
dataType: &quot;xml&quot;,  
contentType: &quot;text/xml; charset=utf-8&quot;,  
processData: false,  
url: path,  
data: fetchRequest,  
beforeSend: function( xhr ){  
xhr.setRequestHeader( //without the SOAPAction header, CRM will return a 500 error  
&quot;SOAPAction&quot;,  
&quot;http://schemas.microsoft.com/xrm/2011/ Contracts/Services/IOrganizationService/Execute&quot; //remove the extra space inserted to help this line wrap  
);   
}  
}).done(function(data) {  
//if successful, pass returned xml and the plot label to the charting function  
processData(data);  
}).fail(function(jqXHR, textStatus, errorThrown ) {  
//if unsuccessful, generate an error alert message  
alert( &quot;Request failed: &quot; + textStatus + &quot;\n&quot; + errorThrown );  
});  
$(&quot;#outputdiv&quot;).append(&quot;Ajax request complete. Output will be processed asynchronously. &lt;br /&gt;&quot;);  
}
</code></pre>
<p>Here are a few things to note:</p>
<ol>
<li>The inside the &quot;done&quot; function is where we tell jQuery what to do when a successful response returns data. We will look at the processData method more closely in the next section.</li>
<li>The &quot;fail&quot; function generates an alert window with error output. You could do something more sophisticated.</li>
<li>You probably want to leave all the other ajax configuration options alone unless you have a good reason not to. It took a good bit of trial and error for me to get this right (probably because I was up too late at night working it out, but I digress . . . ).</li>
</ol>
<p><strong>Handling the response</strong></p>
<p>Assuming that everything went according to plan, our callback function will be called with the query results. At this point, you can do anything with them that you would normally do with XML inside of JavaScript. You can also convert the XML to JSON if that's more your speed. For demonstration purposes, I will show how to loop through the results and display the key-value pairs for each field returned.</p>
<p>Before I show the code to process the results, let's take a look at what the results would look like for this theoretical query:</p>
<pre><code>&lt;fetch distinct='false' mapping='logical' aggregate='true'&gt;  
&lt;entity name='contact'&gt;  
&lt;attribute name='fullname' alias='contact_count' aggregate='count' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='day' alias='day' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='month' alias='month' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='year' alias='year' /&gt;  
&lt;/entity&gt;  
&lt;/fetch&gt;
</code></pre>
<p>In this query I am counting the number of contacts created by day, month and year. When I execute it against CRM, I get output that looks like the contents of the attached file: <a href="https://alexanderdevelopment.net/content/images/2013/01/response.xml">response.xml (6.76 kb)</a>  Here are some important points:</p>
<ol>
<li>Each row of data is represented as an &quot;a:Entity&quot; element.</li>
<li>Individual attribute names and values can be found in the an entity's &quot;a:Attributes&quot; element and also in its &quot;a:FormattedValues&quot; element. In this example I will be working with the &quot;a:FormattedValues&quot; element because it's marginally easier to parse, however you may find times that it makes more sense to work with &quot;a:Attributes&quot; instead.</li>
<li>Everything under &quot;a:FormattedValues&quot; is represented as a string, so we would need to convert to other datatypes where necessary (ie. building a date object from the returned month / day / year values).</li>
<li>Each key-value pair under &quot;a:FormattedValues&quot; is contained in an &quot;a:KeyValuePairOfstringstring&quot; element.</li>
</ol>
<p>Now that you know what the response from CRM looks like, here is the method that parses it and writes the output:</p>
<pre><code>function processData(xml) {  
/// &lt;summary&gt;  
/// writes key-value pairs to a div  
/// &lt;/summary&gt;  
  
alert(&quot;Output started&quot;);  
$(&quot;#outputdiv&quot;).append(&quot;OUTPUT FROM CRM &lt;br /&gt;&quot;);  
  
//outer loop  
$(xml).find(&quot;a\\:Entity&quot;).each(function() {  
//write entity  
$(&quot;#outputdiv&quot;).append(&quot;Entity &lt;br /&gt;&quot;);  
//inner loop  
$(this).find(&quot;a\\:KeyValuePairOfstringstring&quot;).each(function() {  
var xmlElement = $(this);  
var key = xmlElement.find(&quot;b\\:key&quot;).text();  
var value = xmlElement.find(&quot;b\\:value&quot;).text();  
$(&quot;#outputdiv&quot;).append(&quot;  Key: &quot; + key + &quot; Value: &quot; + value + &quot;&lt;br /&gt;&quot;);  
  
});  
});  
  
alert(&quot;Output complete&quot;);  
}
</code></pre>
<p>You'll see there are two loops that use the jQuery find method. First the outer loop finds each a:Entity element, and then it passes that element to another function that executes the inner loop to find each a:KeyValuePairOfstringstring element. Then that element is passed to another function that extracts the text of the &quot;b:key&quot; and and &quot;b:value&quot; elements and writes them to the web page output div using jQuery's append method.</p>
<p><strong>Trying it out</strong></p>
<p>Here is a complete web page with the code for you to download and try out in your own CRM instance: <a href="https://alexanderdevelopment.net/content/images/2013/01/jquery_fetchxml.htm">jquery_fetchxml.htm (4.53 kb)</a>. Just upload it as you would any other web resource, publish and open. At that point you will be presented with a screen that looks like this:</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/01/fetch_start.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/01/fetch_start.PNG#img-thumbnail" alt="The FetchXML / JQuery example page"></a></p>
<p>Either leave the pre-populated FetchXML in the textarea or supply your own. Once you click the &quot;fetch and process&quot; button, you will start to see some output and a couple of status alert windows before the output finally displays. The end result should look like this:</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/01/fetch_complete.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/01/fetch_complete.PNG#img-thumbnail" alt="The FetchXML / JQuery example page showing output"></a></p>
<p>As mentioned earlier, the attribute values retrieved are all strings, so you'll see the years have commas in them (2,013 instead of 2013). The solution is to either get the integer value from the XML response or parse the text value into an integer.</p>
<p>Caveats:</p>
<ol>
<li>In the demo web page, I am using the jQuery library hosted by the Microsoft Ajax Content Delivery Network. If your users are accessing a CRM instance on your LAN, it would be better to host the jQuery library inside of CRM.</li>
<li>I don't know how this page hosted as a web resource will work in browsers other than Internet Explorer. Initially I did most of the jQuery prototyping work with a locally stored XML file on my PC using Chrome, and that code didn't work in IE without a lot of changes. Particularly noteworthy is that Chrome could find the XML elements without me needing to specify a namespace (&quot;a:&quot; or &quot;b:&quot;), but IE wouldn't. I did not go back and test whether the modified find selectors worked in Chrome.</li>
</ol>
</div>]]></content:encoded></item><item><title><![CDATA[Simple C# class to populate datatable from FetchXML]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've typically preferred to access Dynamics CRM data using SQL queries, so I have never worked much with FetchXML. I've recently started working on a bit of a hobby project where it makes more sense to populate a datatable from using FetchXML than to use a SQL query, but unfortunately</p></div>]]></description><link>https://alexanderdevelopment.net/post/2012/12/28/simple-c-class-to-populate-datatable-from-fetch-xml/</link><guid isPermaLink="false">5a5837216636a30001b9768b</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[C#]]></category><category><![CDATA[FetchXML]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Sat, 29 Dec 2012 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>I've typically preferred to access Dynamics CRM data using SQL queries, so I have never worked much with FetchXML. I've recently started working on a bit of a hobby project where it makes more sense to populate a datatable from using FetchXML than to use a SQL query, but unfortunately I have encountered three differences between FetchXML and direct SQL that I don't particularly like:</p>
<ol>
<li>FetchXML results do not include attributes that are not populated in CRM, even if they are explicitly requested in the query.</li>
<li>You can't retrieve the label for a picklist using the attribute name + &quot;name&quot; convention.</li>
<li>Your code has to add additional logic to deal with AliasedValues, EntityReferences, etc.</li>
</ol>
<p>Here is a class I wrote to execute a FetchXML query and populate a datatable with the results.</p>
<pre><code>class QueryUtility  
{  
public DataTable ExecuteFetchXml(string fetchXmlFragment, IOrganizationService service)  
{  
//execute fetchxml  
FetchExpression fetch = new FetchExpression(fetchXmlFragment);  
EntityCollection fetchresults = service.RetrieveMultiple(fetch);  
  
DataTable resultsTable = new DataTable(&quot;results&quot;);  
if (fetchresults.Entities.Count &gt; 0)  
{  
for(int i=0;i&lt;fetchresults.Entities.Count;i++)  
{  
var entity = fetchresults.Entities[i];  
DataRow row = resultsTable.NewRow();  
foreach (var attribute in entity.Attributes)  
{  
if (!resultsTable.Columns.Contains(attribute.Key))  
{  
resultsTable.Columns.Add(attribute.Key);  
}  
row[attribute.Key] = getAttributeValue(attribute.Value).ToString();  
}  
foreach (var fv in entity.FormattedValues)  
{  
if (!resultsTable.Columns.Contains(fv.Key + &quot;name&quot;))  
{  
resultsTable.Columns.Add(fv.Key + &quot;name&quot;);  
}  
row[fv.Key + &quot;name&quot;] = fv.Value;  
}  
  
resultsTable.Rows.Add(row);  
}  
}  
return resultsTable;  
}  
  
private object getAttributeValue(object entityValue)  
{  
object output = &quot;&quot;;  
switch (entityValue.ToString())  
{  
case &quot;Microsoft.Xrm.Sdk.EntityReference&quot;:  
output = ((EntityReference)entityValue).Name;  
break;  
case &quot;Microsoft.Xrm.Sdk.OptionSetValue&quot;:  
output = ((OptionSetValue)entityValue).Value.ToString();  
break;  
case &quot;Microsoft.Xrm.Sdk.Money&quot;:  
output = ((Money)entityValue).Value.ToString();  
break;  
case &quot;Microsoft.Xrm.Sdk.AliasedValue&quot;:  
output = getAttributeValue(((Microsoft.Xrm.Sdk.AliasedValue)entityValue).Value);  
break;  
default:  
output = entityValue.ToString();  
break;  
}  
return output;  
}  
}
</code></pre>
</div>]]></content:encoded></item></channel></rss>