Wednesday, September 4, 2013

How to copy an entity using C# plugin and early bound classes

Hello,

In this post I'm going to explain you how to copy an entity by using plugin written in C#. I'm also demonstrating you the power of CrmSvcUtil which "generates early-bound .NET Framework classes that represent the entity data model used by Microsoft Dynamics CRM" for your Visual Studio project. I'm not going through how to use CrmSvcUtil. If you need help getting started with it please refer Create Early Bound Entity Classes with the Code Generation Tool (CrmSvcUtil.exe).

As an example I'm going to use Contact entity. I'm going to attach my plugin in Delete event / message so that when ever the user deletes the contact my plugin will run and copy that contact.

Some prerequisites are

  • You have Visual Studio and know how to create a solution and a project.
  • You have plugin registration tool and know how to register a plugin
  • You have CrmSvcUtil and know how to generate classes and import them as part of your Visual Studio project.
  • You have Microsoft Dynamics CRM SDK (which actually includes plugin registration tool and CrmSvcUtil)
So let's get started. I'm writing this post as I'm doing this task so you may want to do some things in different order maybe.

Step 1

Create a new solution (or use existing one) and add new project into it. There are some assemblies you have to add.
  • Microsoft.Xrm.Sdk (this can be found inside the SDK)
  • Microsoft.Xrm.Sdk.Client
  • System.ServiceModel
  • System.Runtime.Serialization

Step 2

Generate classes by running CrmSvcUtil.exe from console. You may want to check all available attributes from the link I provided in a beginning. As a reference this is how my command looks like

C:\Program Files (x86)\Microsoft Dynamics CRM 2011 SDK\bin>CrmSvcUtil.exe /url:https://antaumus601.crm4.dynamics.com/XRMServices/2011/Organization.svc /out:EarlyBoundClasses.cs /username:"myUsername" /password:"myPassword" /namespace:AntaumusCRMSolution

When the .cs file is ready add it to your Visual Studio project.

Step 3

Write the core plugin components (implement IPlugin interface etc.). If you need help with writing plugin please refer Plug-in Development for Microsoft Dynamics CRM

Step 4

Now let's write the actual logic.Very important part when using early bound types is OrganizationServiceContext class. Please refer Use the Organization Service Context Class. In this case it will help us to add our new contact easily to CRM but it has a lot of good benefits (for example LINQ providing).

"To instantiate the context class, you must pass the class constructor an object that implements the IOrganizationService interface."

Fortunately we can create IOrganizationService indirectly from IServiceProvider that is passed for Execute method by writing following lines

IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(executionContext.UserId);
OrganizationServiceContext orgServiceContext = new OrganizationServiceContext(service);  

So in shortly what happens here is we take IOrganizationServiceFactory from service provider and then use the factory for creating a service. If you want to know more about factories this might be good place to start: Exploring the Factory Design Pattern

Now when everything is settled you can create new entities like this

Contact newContact = new Contact();

And access its properties like this

newContact.FirstName

You can add entity / entities for set OrganizationServiceContext is tracking by using AddObject method. When running SaveChanges() function all changes are  performed for entities that are in the set.

Very simple. I'm not going to explain my whole code here but instead I'll paste it to the end so you can take a look at it by yourself. To keep it very simple I did not copy whole contact in my code, only first name and last name. The approach I'm using in this example may not be the best. If I should really copy the whole contact (and related entities) I might think about using LINQ for sure.

Step 5

Register your plugin in a way you want. I registered it in Post-operation Delete message synchronously and created Pre Entity image. You may have to sign you Visual Studio project first.



















Final result