Microsoft Dynamics 365 Blog

We welcome back Aaron Elder, one of our favorite CRM MVP guest bloggers with some helpful tips from the field.

A month or so back, I was having lunch with the SDK documentation team and they asked me “does anyone really use the helpers?” to which, I responded “absolutely”, I then proceeded to agree to writing a blog post on the topic and that is the basis for today’s post.

First off, what are the “helpers” and why do so few people seem to know about them?  They have been in the SDK for quite some time and they are not very hard to use.  I think the problem is that people may not know how to put them to good use on their projects.

I think the first thing to do is to explain what the helpers are and what they can do for you.  The SDK does a pretty good job of explaining what these little guys can do.

“You can add this helper code to your solution to simplify the code that you have to write using QueryExpression.  The helper code also provides static types that can be used for getting and setting attribute values that are not provided in the Web Services Description Language (WSDL).

The helper code can be found in the following folder in the SDK download package: sdk\server\helpers\cs\crmhelpers.

Helper code that contains enumerations, constructors for system types, and classes to help build queries.”

The SDK then goes on to enumerate and describe all of the classes and tools that have been provided… there is a “Readme.doc” file in the helper folder with instructions with how to integrate them in your project. 

So with all this great documentation, why does it seem that so few developers make use of these.  While I have many theories, let’s keep this post to the facts… the facts on how Ascentium has made use of them and the facts about what makes these guys so useful as well as a bit of background and history on the topic.

The root of the problem is that the Web Service Definition Language does not support describing client or consumer side logic, the kind of logic you would use to build constructors, indexers, accessors and methods that could execute on the client prior to serialization and transport of the message.  This means that for CRM types that need to be constructed before they can be set, you have to write code that looks something like this:

asc_entity myEntity = new asc_entity();

myEntity.asc_number = new CrmNumber();

myEntity.asc_number.Value = 12;

WSDL is able to describe what an “asc_entity” and “CrmNumber” are, but it can’t define a constructor on the type CrmNumber that takes in an integer and sets its Value property.

This and many other similar situations is where the “helpers” come.  In CRM 3.0, which was in the .NET 1.x time period, provided a simple set of utility classes to make the code above a little bit easier.  This looked something like this:

asc_entity myEntity = new asc_entity();

myEntity.asc_number = Helper.CreateCrmNumber(12);

Obviously an improvement, especially for more complex types like Lookups.  With the move to CRM 4.0 and the progression to .NET 2.0; partial types provide a much more elegant solution in the CRM 4.0 SDK.  The type helpers now look something like this:

asc_entity myEntity = new asc_entity();

myEntity.asc_number = new CrmNumber(12);

This new approach in CRM 4.0 is much better than previously and the time saving benefits that can be found by using the helpers provided by Microsoft and writing a set of your own can be tremendous… assuming your team knows about them.

The SDK does a pretty good job of discussing all of the helpers available, some of my favorites include:

  • Query Expression Helpers : This is a bunch of helpers that make creating Query Expression objects a lot easier.
  • Type Helpers : Makes creating CRM data types a lot easier.
  • Dynamic Entity Helpers : These add things like indexers, dynamic property helpers and helpful methods like Contains to the WSDL-based Dynamic Entity.

The SDK also provides a “Full Sample” that demonstrates how to use the helpers.  This is located here:

\SDK\Server\FullSample\UsingHelpers

How Ascentium uses the Helpers

To give everyone an idea of how we use these helpers.  We, as a standard have something we call “the standard build tree”, this is a basic clean CRM project that starts out with a vanilla WSDL proxy CS files with the namespace Ascentium.Crm.Common.Sdk.CrmServiceSdk.  These are then checked in our standard tree under \Common\Sdk.  We then also include a copy of the “helpers” (\Common\Extensions), along with our own helpers that exist in the same namespace, using the same partial type method.  Here is an example of an extension we made to the CrmService to make use of the auto-impersonator.

   1: \Common\Extensions\CrmService.cs
   2:  
   3: using System;
   4: using System.Collections.Generic;
   5: using System.Text;
   6:  
   7: namespace Ascentium.Crm.Common.Sdk.CrmServiceSdk
   8: {
   9:        public partial class CrmService
  10:        {
  11:              public BusinessEntityCollection RetrieveMultiple(QueryBase query, bool useImpersonator)
  12:              {
  13:                     if (useImpersonator)
  14:                     {
  15:                            using (new Microsoft.Crm.Sdk.CrmImpersonator())
  16:                            {
  17:                                  return this.RetrieveMultiple(query);
  18:                            }
  19:                     }
  20:                     else
  21:                     {
  22:                            return this.RetrieveMultiple(query);
  23:                     }
  24:              }
  25:        }
  26: }

The provided helpers are definitely useful and when integrated into our default build system, they are seamlessly available for use and provide a great deal of benefit at an exceptional low cost.  Since we include a vanilla WSDL in our build tree, we also include a handy script to regenerate these from a VPC.  This allows developers to quickly re-build the WSDL as they make customization and check in their project-specific WSDL proxies.  The code for this is as follows:

   1: \common\sdk\regenerate_proxies.cmd
   2:  
   3: @echo off
   4: cls
   5: echo.
   6: echo NOTICE: This script generates WSDL Proxies for the DEFAULT ORGANIZATION on the site
   7: echo http://localhost:5555 - If this is a multi-organization box, you will need to update this script
   8: echo to point to the proper organization
   9: echo ================================================================================================
  10: echo Also note, this script regenerates all proxies, however under normal circumstances only the
  11: echo CrmService Proxy will change.
  12: echo.
  13: pause
  14:  
  15: echo Generating CrmService SDK for default organization
  16: wsdl.exe /out:CrmService.cs /namespace:Ascentium.Crm.Common.Sdk.CrmServiceSdk http://localhost:5555/mscrmservices/2007/crmservice.asmx?wsdl
  17:  
  18: echo Generating Metadata SDK
  19: wsdl.exe /out:MetadataService.cs /namespace:Ascentium.Crm.Common.Sdk.MetadataServiceSdk http://localhost:5555/mscrmservices/2007/metadataservice.asmx?wsdl
  20:  
  21: echo Generating CrmDiscoverService SDK
  22: wsdl.exe /out:CrmDiscoveryService.cs /namespace:Ascentium.Crm.Common.Sdk.CrmDiscoveryServiceSdk http://localhost:5555/mscrmservices/2007/AD/crmdiscoveryservice.asmx?wsdl

Enjoy,

CRM MVP Aaron Elder

Disclaimer:

This posting is provided "AS IS" with no warranties, and confers no rights.

We're always looking for feedback and would like to hear from you. Please head to the Dynamics 365 Community to start a discussion, ask questions, and tell us what you think!