MS Dynamics CRM provides several web service endpoints. This is one of those endpoints, for organisation service.
One of the greatest benefits using this endpoint is to create a context class derived from CrmOrganizationServiceContext
, which works as like DbContext
from Entity Framework. The context class can be generated by CrmSvcUtil.exe
that is shipped in CRM SDK.
When you directly run the following command in the Command Prompt screen, or put the command in build.bat
and run the batch file, one single file defined in the /out
parameter is generated:
However, there are problems using the generated file:
- There are number of entities defined in CRM, but there is only one file generated.
- Each entity can have tens to hundreds of fields (or properties).
- Not all entities are necessary for generation.
Due to the reasons stated above, even if a very new CRM instance is used to generate the context file, the size of the file is more than 6.5MB, which is huge. If CRM is customised based on business requirements, more entities and fields are generated, which results in the bigger size of the generated file. It is not desirable. I’m not happy at all.
Fortunately, CrmSvcUtil.exe
provides an interface called ICodeWriterFilterService
. With this interface, only selected entities are filtered and generated as strongly-typed classes. In addition to this, those filtering entities can be set up in a various type of configuration files such as XML, JSON or YAML. In this post, I’m going to show how to implement ICodeWriterFilterService
to filter out entities defined in a configuration file in XML, JSON or YAML.
The complete sample code can be found at this repo.
Implementing ICodeWriterFilterService
Within the CRM SDK or this page, you can find the sample code to generate extension codes. Based on that sample code, a new EntityFilteringService
class is created for our purpose:
- You can find the
GenerateEntity()
method. It acceptsEntityMetadata
instance as a parameter and validates its entity name – if it’s valid, create the entity; otherwise ignore it. - You can also find
IFilterItemCollection
interface within the constructor. This creates an instance deserialised from a setup file for entity filtering and validates the entity name.
That’s what the EntityFilteringService
only does. Once IFilterItemCollection
instance is properly implemented, it just works. Now, let’s create classes implementing that interface.
Implementing IFiterItemCollection
First of all, the IFilterItemCollection
interface defines one method, IsValidEntity(entityName)
.
Then that method is implemented in the FilterItemCollection
class.
Please note that this FilterItemCollectionClass
has the modifier of abstract
. As stated above, the filtering setup file can be any format like XML, JSON or YAML. Therefore any corresponding class should inherit this base class. Let’s move onto implementing concrete classes for each setup file format.
XmlFilterItemCollection
If you are an XML person, setup file might be filter.xml
and its structure looks like:
Therefore, read the XML file and deserialise it.
JsonFilterItemCollection
If you prefer JSON, create filter.json
like:
And deserialise it.
YamlFilterItemCollection
If YAML is your preference, get filter.yml
like:
And deserialise it. YamlDotNet
makes your life easier for this operation.
All done! Regardless the setup file is filter.xml
, filter.json
, or filter.yml
you can filter out entities only necessary. So, how to apply it? There’s only one step left. Let’s have a look.
build.bat
and CrmSvcUtil.exe.config
Firstly, CrmSvcUtil.exe
needs its configuration file, CrmSvcUtil.exe.config
. We can add “ node for configuration like:
They can be passed within the command prompt, if you like.
language
: To define language to generate proxy file.out
: To define the filename for generation. eg)OrganisationService.cs
serviceContextName
: To define service context class inheritingCrmOrganizationServiceContext
. eg)OrganisationServiceContext
codeCustomization
: To point the assembly for filtering extension.codeWriterFilter
: To point the assembly that contains the actual filtering logic.
Once completed, create build.bat
looking like:
Inside the batch file, you can setup the CRM service endpoint URL and namespace for output. Also you can ask the user manually type their username and password. Make sure that the password is NOT masked in this example, which is not secure.
Done! Run the build.bat
and you’ll be able to see the OrganisationService.cs
file generated. So, how can we apply this generated class? Let’s create a Web API app for test. There is a simple Web API app included in the sample code.
Web API Application
The generated OrganisationService.cs
has the OrganisationServiceContext
class. As this is a partial
class, we can extend this class by implementing a new interface, IOrganisationServiceContext
for testing and DI purpose. Of course, you can directly use the contet class without it.
IOrganisationServiceContext
In fact, the CrmOrganizationServiceContext
class is very similar to the DbContext
class, only IQueryable
properties need to be defined in the interface. Then implement it with another partial class of OrganisationServiceContext
.
One of the reasons using the interface is to write mocking for test codes. Also it’s good for dependency injection with IoC containers. If you use Autofac
, for example, the following code snippet shows how to register dependencies.
Now, all setup. You can use OrganisationServiceContext
as if you are using Entity Framework.
The result will look like:
So far, we have implemented and applied CRM organisation service context by filtering selected entities with various types of setup files. With this, CRM integration for other applications will be much easier and faster. CRM 2015 also provides REST-basis Web API. This is still at early stage but yet powerfull so will be discussed in another post sooner or later.
Thanks for sharing.