Creating early-bounds manually

Creating early-bounds manually

Wait, what? Who on earth would do such terrible thing? For those of you who are not aware of that (are there any?), there is a great tool included inside SDK binaries, which is called “crmsvcutil.exe” and allows to generate proxy classes that can be used for calling Dynamics 365 Organization Service (for commands and query operations). If you have ever worked with any WCF service, you’ll probably know a tool called “svcutil.exe” which basically does the same thing – only here this tool adds some extra metadata, which is used under the hood by CRM SDK to convert correctly the proxy (often referred to as “early-bound class”) to Entity class object, which is in fact the class used by the Organization Service in most of its methods.

Having said that, you probably wonder, why I even consider not using this tool. It greatly improves the coding performance, it gives the developer intellisense, nobody has to use any magic strings – everything is strongly typed and most of the errors can be found at compile time. Yes, that is totally correct – but you also have this XX-thousands lines long file, which is taking years to open and making your VS cry, when you do so, your DLL with logic takes 10MB instead of 100KB, because of that file (not mentioning PDB file…), all the custom properties and custom entities are not following .NET naming convention (being lowercase with some silly prefix like “new_” or whatever you choose it to be). Also have a look at your recent project – how many entities and attributes have you used in there to justify generation of thousands of unnecessary classes, enums, fields and attributes? If you would say that in % of total code, it would not be larger than 10% (I dare you to check!).

I understand that there are some third party tools, or even open-source tools to generate proxies not for all entities but only for some chosen ones. These things are great, but they still produce some code, that we cannot control (under the hood they are still using “crmsvcutil.exe”) and do not fix the problem of naming fields or generating all 150 properties for Account, even if we need only 10 of them in our plugin/external application.

Of course, I don’t suggest to skip using proxy classes – I’m a big fan of them. What I suggest, is trying to build your own model of proxy class – without any special tool. You will have full control of what they contain, how they can behave and how many of them are there in your project. I’m not talking here about systems containing one plugin, that simply does the only one thing ,that could not have been achieved by workflow, business rule or calculated field. I’m talking about big, enterprise-class systems, which require hundreds or thousands of man-days to be built – including some fancy integrations with external systems, many plugins or custom workflow activities, following the best modern approaches of code engineering, like high coverage of unit tests. In such systems, keeping clean model and including only the things that the application is actually using is a crucial part. I will not write about technical debt and all those standard phrases that will tell you that the more time you will spend developing good and clean code, the less time you will have to spend after a year when you will have to fix something or extend your application. Writing your own proxy class is not hard at all and I assure you that once you start to do so, you will not spend too much of your time for that. Also one more thing before I start showing you the code – why creating a model in WCF, MVC or MVVM application is not a problem for you and it is in Dynamics 365?

Ok, so let’s go to some examples. I will be using C# 7.0 features, so make sure you have Visual Studio 2017 installed, if you want to try my examples. I will start from creating some class called MyAccount that I will use to query some Account data from CRM. It will look like that:

And I will try to use it like that:

Unfortunately, this will crash with the following error:

System.ArgumentException: ‘The specified type ‘DemoCodeNoProxy.MyAccount’ is not a known entity type.’

Well, this makes sense – we never told the OrganizationService client, how it can serialize/deserialize our custom class into something that it understands. First thing we should do is adding Microsoft.Xrm.Sdk.Client.ProxyTypesAssemblyAttribute to the .dll file which has our custom model, I usually do this inside AssemblyInfo.cs file:

We need to decorate our class with proper Microsoft.Xrm.Sdk.Client.EntityLogicalNameAttribute:

If we will run our code now, we will get another exception:

System.ServiceModel.FaultException`1: ‘attributeName’

Not saying much I have to admit, but problem is quite easy to guess – LINQ to CRM has to map our strongly typed properties to attribute names on CRM side. This is simply done by odding Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute for our property:

We can now run our code and… it works correctly! Great. Now let’s improve it a little to really boost our productivity. First thing I would do would be renaming property from “odx_clientcode” to “ClientCode” to follow standard C# naming convention. Can we simplify the code for our property? Sure let’s create a base class for all our custom proxy classes:

As you can see, I’m using some convention here – I’m assuming that all my Dynamics365 attributes are named the same as my properties in my model – but only with lowercase and prefix. If I follow this convention and use the above class, I can simplify my proxy class to look like that:

As you can see, adding new properties requires really little effort. If you don’t like to follow my convention (because you don’t have control over the CRM naming), you can pimp it up further by reading names of attributes from AttributeLogicalNameAttribute, so that you are sure to be using right name. Very simplified version of such approach can look like that:

So we need only to add an attribute with proper name for our class and each property – everything else will be done automatically, there are no more places where we use the logical names from CRM. Isn’t it great?

MyEntity class is also a great place to add any commonly used methods which can simplify your work even more. Good luck!

Authors:

Pawel Gradecki

Subscribe to oneDynamics

Sign up now to get access to the library of members-only issues.
Jamie Larson
Subscribe