Dynamics Template-based Code Generator – Supercharged – Overview | Mage Series
Microsoft provides a tool within the Dynamics SDK called CrmSvcUtil
. It generates early-bound entity code, which includes classes for each entity in CRM with properties for each field and relation. Microsoft’s Dynamics early-bound entity generator provides basic functionality through a command-line interface. In this article, I am going to introduce the Dynamics Template-based Code Generator whose only goal is to make our (developers’) lives easier.
The first part of this article will highlight some of the tool’s features. I won’t go into too much detail, as I want to give you an idea of what is offered. Specifics, details, and how-tos will be covered in later parts of the article.
TL;DR, the Visual Studio extension can be found here, and the XrmToolBox plugin here.
CrmSvcUtil
The official tool produces SDK-specific properties, like EntityReference
and OptionSetValue
, which requires a tiny bit of extra work to map to a more generic type that is more suited when communicating with an external party. From a CRM developer perspective, we would rather use .NET value-type and primitive types; e.g. when dealing withOptionSetValues
, we have to manually define those values somewhere in the code to avoid magic numbers. Early-bound is hinged on alleviating this type of issues.
By default, the utility generates all entities, in order to limit the number of entities generated, we have to create an XML definition file (steps here). It’s a step in the right direction, but still, you have to manually configure the names by hand.
Finally, the generated code is based on a hard-coded template, which is hard to modify. In addition, the tool is external to the target projects’ IDE (Visual Studio), which leads to an inconvenient context switching or requiring manual configuration per project.
Improvement Steps
Taking the above into consideration, there are a few areas and ideas that could make our lives so much easier.
First, create a UI that can easily filter the list of entities generated. That has been realised by our community in the form of XrmToolBox plugins. Those tools also support replacing the OptionSetValue
type with safer enum-based types.
Let’s take this a few steps further and supercharge a-near-daily activity in our development workflow. In the next few sections, I will demonstrate the features of the custom Dynamics Template-based Code Generator Visual Studio extension.
Visual Studio Integration
Back in 2015, I found a gem of a tool created by Eric Labashosky. The tool did what the SDK tool did exactly, except, it provided a UI integrated into Visual Studio. Furthermore, it provided a per-project T4 template that greatly facilitated customising the generated code in ways only the SDK tool can dream of.
I had such a vision for this tool, that I took it upon myself to expand it to new heights. Thank you, Eric, for such a cool and innovative idea.
Dynamics Template-based Code Generator
The tool gives the following benefits:
- Built for Visual Studio
- You never have to leave Visual Studio to regenerate the code
- All the configurations are saved in the project itself, which facilitates Version Control
- Preserves the original
CrmSvcUtil
structure and logic - Customize the way the code is generated
- You get a default T4 template for the code that is generated, with a multitude more features than the official tool (features below)
- You can rewrite the whole template if you wish for any possible requirements
- Replaced the SDK types with .NET types
- E.g.
OptionSetValue
=>Enum
(Enum[]
for Multi-select),EntityReference
=>Guid
,Money
=>decimal
, … etc.
- E.g.
- Generate only what’s needed
- Only choose the entities required
- Only the fields required
- Additional control
- Option to use display names of entities and fields as variable names instead of logical names
- Override field names inside the tool’s UI
- Ability to Lock variable names to avoid code errors on regeneration
- Greatly enhanced regeneration speed by only fetching changed metadata from the server
- Support for strongly-typed alternate keys, for entities and
Entity References
- Add annotations for model validation
- Generate metadata
- Field logical and schema names
- Localised labels
- Many options to optimise generated code size even further
- Define web service contracts with different profiles
- Option to mark certain fields as ‘read-only’
- Generate concrete classes for CRM Actions
- Support bulk relation loading
- Support filtering on relation loading
Installation
The tool can be easily installed as a Visual Studio extension from the marketplace (here). Also available as an XrmToolBox plugin (here).
The base code for the original tool by Eric can be found here.
Adding a Template
The first step is simple:
Configuring the Tool
The configuration is used at the discretion of the templates. You can create your own template and use the configuration however you see fit. As such, the description below is only from the perspective of the default template.
Many options have a tooltip if you hover for 1 second or more.
Start it up
After adding the template, the tool is started automatically. If that doesn’t happen, you can always start it manually:
Define the connection parameters
Insert the connection string:
Select the entities
Click on ‘Early-bound and Metadata’ button.
The table displays the list of entities on your CRM server. The checkbox on the left selects the entity for generation, and the checkboxes on the right function as follows:
- Early-bound: generate the entity attributes.
- Apply Filter: when you double click the entity name, a filtering window appears. This option applies that filtering to the generated code; otherwise, it will be ignored, except renaming.
- Generate Metadata: generate class and constants for field logical names, schema names … etc.
- Option-set Labels: generate properties that contain all localised labels of option-set values.
- Lookup Labels: generate properties that contain the localised labels of lookup fields.
- Select Actions: generate concrete classes for the selected Actions. Global Actions are generated from the General Options window.
The filtering textbox at the top filters the list of entities — acts as a search box.
Filter Fields and Relationships
Double-clicking any entity name opens up the following window:
In this window, you can select which fields and relationships you want to generate, and rename those items if required (renaming is optional). However, the default template ignores other options (clear mode, flattening … etc.) for CRM entities. It will apply filtering only when ‘Apply Filter’ is selected for said entity, and only renaming is taken into account.
Contracts
Although the Dynamics Template-based Code Generator (and template) provides the option to adapt the SDK Entity
objects to be serialised and communicated directly across web services, some architects prefer using specific contracts that satisfy the CQRS pattern in some way (more details here). That pattern requires much more than simple filtering for generated classes on the same fields; however, the tool provides the simple ability to define different contracts for different operations. E.g. you might want to share most fields on the entity on retrieve but only allow updating 2 or 3 fields only.
The template provides two convenience extension methods to convert between CRM Entity
and Contract
objects, namely ConvertTo
.
Click on the ‘Web Service Contracts’ button to access the contracts window. The options here are fairly similar to the ones in the CRM Entity window. You can access the field filtering by double-clicking an entity.
Clear value
An additional option is provided: ‘Clear Mode’, which changes the behaviour of dealing with ‘clearing’ values when saving to CRM, in other words, how to deal with null
values. This effect is observed when ConvertTo
is called. Possible values for this option:
- Default: uses the global setting option.
- Disabled: do not clear any CRM field values at all, regardless of the value provided through the contract object.
- Empty: if a contract field is empty, clear the value of the corresponding field in CRM.
- Convention: use certain value in the contract field object as a ‘convention’ to clear value in the CRM object; e.g. a value of -1 in an enum field, a 1970 date, a
int.MinValue
for integers, aGuid.Empty
forGuid
fields … etc. - Flag: this option is a bit messy, in that it creates a property for each field that clears its corresponding field when set to ‘true’.
Filtering additional options
In the filtering window, some options that are ignored by CRM entities will now have an effect with contracts:
- Read-only: the field value will be ignored when converting a contract object to a CRM one.
- Clear Flag: generate a
Flag
property as described above. - Language: sets this field as the label value for any lookups of this entity for this language.
- Flat: takes N-1 relation entity fields, and creates properties in the parent entity with its name as the prefix.
Flattening a relation
For relations, the template generates either an array of a related entity class or simply a property of the related entity type. E.g. if we have an Account
entity that is related to a Contact
by a 1-N relation, a property of type Contact[]
will be created under the Account
class. Another property of type Account
will be created under the Contact
class, representing the lookup there.
If we flatten that relationship, the template will create a property for each field in the Account
under the Contact
entity; e.g. AccountNumber
on the Account
entity will become Account_AccountNumber
under the Contact
class.
Global Settings
Click on the ‘gear’ icon at the bottom to open the settings window:
The global settings are mostly self-explanatory. In addition, hovering over some options will result in a descriptive overlay popping up after 1 second or so. Please post a comment/question here if you have any enquiries, and I will provide more details in this article.
Conclusion
The official SDK utility provides a great way to statically bind your CRM code; however, it’s not very convenient to use and results in a large code size unnecessarily. The Visual Studio extension I described in this article makes dealing with entity-based code generation a breeze for developers.
Now that we have gone through a quick overview of the Dynamics Template-based Code Generator VS extension, in the next part of the article, we will go into more detail, delving into some features, and exploring the generated code using the default template.
Hi! This is a great article about Dynamics Template-based Code Generator. I appreciate you explaining the benefits and improvements of this tool. It’s interesting to know that the tool replaces SDK-specific properties with .NET value-type and primitive types, and generates only what is needed. The feature of generating metadata, including field logical and schema names and localised labels, is also very helpful. Thanks for sharing!
Thank you for your feedback. 🙂
Hey there. Love the generator. But getting serialization errors when attempting to create new early-bound classes. The error mentions the attributes missing the DataMemberAttribute. But the classes have the DataContract attribute.
The full XML error below. Would appreciate advice!
======================================================================
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=8.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Unexpected exception from plug-in (Execute): FPC.CRM.OnPremise.Plugins.ProcessSegregationStaging: System.Exception: Unhandled Exception in SegregationTaskHelper(): Type ‘FPC.CRM.OnPremise.Plugins.GeneratedEntity`1[FPC.CRM.OnPremise.Plugins.Segregation+RelationName]’ cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.Detail:
a5ac3d1e-852d-45ec-8e3f-b1a0e204115e
-2147220956
Unexpected exception from plug-in (Execute): FPC.CRM.OnPremise.Plugins.ProcessSegregationStaging: System.Exception: Unhandled Exception in SegregationTaskHelper(): Type ‘FPC.CRM.OnPremise.Plugins.GeneratedEntity`1[FPC.CRM.OnPremise.Plugins.Segregation+RelationName]’ cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
2023-10-18T15:46:25.1546759Z
false
[FPC.CRM.OnPremise.Plugins: FPC.CRM.OnPremise.Plugins.ProcessSegregationStaging]
[7cafe2e2-1d6c-ee11-81a8-0050563b3dc7: FPC.CRM.OnPremise.Plugins.ProcessSegregationStaging: Create of tcs_segregationstaging]
Hello, Nipper,
Thank you for reporting the issue. I would appreciate reporting issues on GitHub, as it’s easier to track and more efficient.
What was the plugin trying to do when the exception was thrown?