This is a cross-posting of Testable Entity Filtering for Service Context on Dynamics CRM 2015 at Kloud.
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.
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 https://github.com/devkimchi/Dynamics-CRM-2015-Filtering-Sample
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 accepts
EntityMetadatainstance as a parameter and validates its entity name – if it’s valid, create the entity; otherwise ignore it.
- You can also find
IFilterItemCollectioninterface 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.
First of all, the
IFilterItemCollection interface defines one method,
Then that method is implemented in the
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.
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.
If you prefer JSON, create
And deserialise it.
If YAML is your preference, get
And deserialise it.
YamlDotNet makes your life easier for this operation.
All done! Regardless the setup file is
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.
CrmSvcUtil.exe needs its configuration file,
CrmSvcUtil.exe.config. We can add
<appSettings> 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)
serviceContextName: To define service context class inheriting
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.
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.
In fact, the
CrmOrganizationServiceContext class is very similar to the
DbContext class, only
IQueryable<T> properties need to be defined in the interface. Then implement it with another partial class of
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.