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.”
“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;
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);
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);
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:
The SDK also provides a “Full Sample” that demonstrates how to use the helpers. This is located here:
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.
3: using System;
4: using System.Collections.Generic;
5: using System.Text;
7: namespace Ascentium.Crm.Common.Sdk.CrmServiceSdk
9: public partial class CrmService
11: public BusinessEntityCollection RetrieveMultiple(QueryBase query, bool useImpersonator)
13: if (useImpersonator)
15: using (new Microsoft.Crm.Sdk.CrmImpersonator())
17: return this.RetrieveMultiple(query);
22: return this.RetrieveMultiple(query);
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:
3: @echo off
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.
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
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
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
CRM MVP Aaron Elder
This posting is provided "AS IS" with no warranties, and confers no rights.
PingBack from http://hoursfunnywallpaper.cn/?p=6187
These helpers have been immensely helpful in CRM 3.0, but I find that the helpers don't help in Plugins, as you have no partial classes to bolt them onto - no web reference.
I would appreciate it if you have any ideas as to how the helpers could be rewritten to not use partial classes, but be standalone helpers (why didn't MS think to include the code by default in their Microsoft.Crm.Sdk namespace!?@*&
Okay, so I'll give you a baker's dozen of some really good stuff from the perspective of a Microsoft
In addition to the stand-alone cs files that you can add to your projects, the helper code is also built into the Microsoft.Crm.Sdk.dll that you use in Plug-ins. This includes the type helpers, the QE helpers and the Dynamic entity helpers.