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.
https://gist.github.com/justinyoo/96e5b5dd3a25343044a7
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:
https://gist.github.com/justinyoo/4229dbb8b385e744db5c
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 https://github.com/devkimchi/Dynamics-CRM-2015-Filtering-Sample
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:
https://gist.github.com/justinyoo/8b4f82dc7bafca780c15
- 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)
.
https://gist.github.com/justinyoo/1379daed7fa0d5213067
Then that method is implemented in the FilterItemCollection
class.
https://gist.github.com/justinyoo/13a0f7179bb2350fe835
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:
https://gist.github.com/justinyoo/cbb3d12a9bab9583899f
Therefore, read the XML file and deserialise it.
https://gist.github.com/justinyoo/462b1cf564c8421c34e2
JsonFilterItemCollection
If you prefer JSON, create filter.json
like:
https://gist.github.com/justinyoo/dd1eb19e012221078b1b
And deserialise it.
https://gist.github.com/justinyoo/f6a451c44b34bcb62f28
YamlFilterItemCollection
If YAML is your preference, get filter.yml
like:
https://gist.github.com/justinyoo/aa10f921fca99495f13c
And deserialise it. YamlDotNet
makes your life easier for this operation.
https://gist.github.com/justinyoo/9742709b60774a642a2d
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 <appSettings>
node for configuration like:
https://gist.github.com/justinyoo/362f7f974749cb717dbe
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:
https://gist.github.com/justinyoo/21d97430acf43f15ba4e
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
https://gist.github.com/justinyoo/be0622e49525baa59005
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 OrganisationServiceContext
.
https://gist.github.com/justinyoo/c24d288c53aa320c9601
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.
https://gist.github.com/justinyoo/1e6aba327beb60895a40
Now, all setup. You can use OrganisationServiceContext
as if you are using Entity Framework.
https://gist.github.com/justinyoo/c9adc17279089057fea0
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.