In the first post of the series (see Part 1), I was dealing with the creation of a new entity which can be used to store the autonumbering parameters such as: which entity must get a number, which attribute must store the number, the number length, the prefix & suffix, etc.
In this second post, we will see how to generate the autonumber by using a plugin.
I’ll use Visual Studio 2010 with C# to create this plugin and then show how it work in real life.
- First step, open VS 2010 Image may be NSFW.
Clik here to view. - Next, create a new ‘Visual C# Windows Class Library’ project (you can choose either the .NET Framework 3.0 or 3.5)Image may be NSFW.
Clik here to view. - Add a reference to the two following Microsoft assemblies given with the Microsoft CRM SDK (these DLLs are located under the CrmSdk\bin folder; make sure you choose the right version: 32-bits or 64-bits)
- Microsoft.CRM.Sdk.dll
- Microsoft.CRM.SdkTypeProxy.dll
- Next step, sign your assembly before doing anything else
- Right-click on your project and select ‘Properties’
- Select the ‘Signing’ menu
- In the drop-down list, choose to create a new strong name key file by selecting the “<New…>” optionImage may be NSFW.
Clik here to view. - Type in a key file name and choose a strong password
- Visual Studio will then create a ‘.pfx’ file which will be attached to the assembly
- Rename the created C# class to whatever you like and put the code listed above (the code is self-explanatory):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Security.Cryptography; using Microsoft.Crm.Sdk; using Microsoft.Crm.SdkTypeProxy; using Microsoft.Crm.Sdk.Query; namespace xRM.AutoNumberPlugin { /// <summary> /// Class that generates a random number for the Test Entity /// </summary> public class TestEntityAutoNumber : IPlugin { public void Execute(IPluginExecutionContext context) { DynamicEntity entity = null; // Verify we have an entity to work with if (context.InputParameters.Properties.Contains("Target") && context.InputParameters.Properties["Target"] is DynamicEntity && context.MessageName.Equals("Create")) { // Obtain the target business entity from the input parameters. entity = (DynamicEntity)context.InputParameters.Properties["Target"]; if (!context.OutputParameters.Properties.Contains("id")) { return; } // Verify that the entity represents a test entity if (entity.Name != "new_testentity") { return; } } else { return; } try { // Verify that the ID is returned upon creation of the test entity string entityId = context.OutputParameters.Properties["id"].ToString(); Key entityKey = new Key(); entityKey.Value = new Guid(entityId); // Get a new instance of the CRM service from the context ICrmService service = (ICrmService)context.CreateCrmService(true); // Create the query on the auto number entity QueryByAttribute query = new QueryByAttribute(); query.ColumnSet = new AllColumns(); query.EntityName = "xrm_automaticnumber"; query.Attributes = new string[] { "xrm_entityname" }; // The entity name you're looking for, selected from the drop-down list (see the how-to part 1) query.Values = new string[] { "new_testentity" }; // Create the request based on the above query RetrieveMultipleRequest request = new RetrieveMultipleRequest(); // Set the request properties request.Query = query; request.ReturnDynamicEntities = true; // Execute the request and get the response RetrieveMultipleResponse response = (RetrieveMultipleResponse)service.Execute(request); string prefix = null; string suffix = null; int length = 1; // Parse the response to get the values you want // (there should be only one record for the same entity) foreach (BusinessEntity be in response.BusinessEntityCollection.BusinessEntities) { if (((DynamicEntity)be).Properties.Contains("xrm_prefix")) prefix = ((string)((DynamicEntity)be)["xrm_prefix"]).ToString(); if (((DynamicEntity)be).Properties.Contains("xrm_suffix")) suffix = ((string)((DynamicEntity)be)["xrm_suffix"]).ToString(); if (((DynamicEntity)be).Properties.Contains("xrm_length")) length = ((CrmNumber)((DynamicEntity)be)["xrm_length"]).Value; } // Generating a random number based on the cryptographic library char[] chars = new char[10]; string a; a = "1234567890"; chars = a.ToCharArray(); byte[] data = new byte[1]; RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider(); crypto.GetNonZeroBytes(data); data = new byte[length]; crypto.GetNonZeroBytes(data); StringBuilder result = new StringBuilder(length); foreach (byte b in data) { result.Append(chars[b % (chars.Length - 1)]); } // Update the new entity's number attribute with the retrieved prefix & suffix and add the random number PropertyCollection properties = new PropertyCollection(); properties.Add(CrmTypes.CreateStringProperty("new_testentitynumber", prefix + "-" + result.ToString() + "-" + suffix)); properties.Add(CrmTypes.CreateKeyProperty("new_testentityid", entityKey)); entity.Properties = properties; // Creating a target update message to alter the newly created entity TargetUpdateDynamic updateEntity = new TargetUpdateDynamic(); updateEntity.Entity = entity; // Creating a request on the server UpdateRequest updateRequest = new UpdateRequest(); updateRequest.Target = updateEntity; // Updating the entity by using the created ICrmService UpdateResponse updated = (UpdateResponse)service.Execute(updateRequest); } catch (System.Web.Services.Protocols.SoapException ex) { throw new InvalidPluginExecutionException("An error occurred in the TestEntityAutoNumber plug-in.", ex); } } } }
- Compile your code and copy your assembly over to your server (I prefer this method)
- Launch the “Plugin Registration Tool” on the CRM server and connect to the desired organizationImage may be NSFW.
Clik here to view.- Once connected to the correct organization, the right screen will display the list of already deployed plug-ins Image may be NSFW.
Clik here to view.
- Click on ‘Register’ and select the ‘Register New Assembly’ option from the toolbar, or use CTRL – A Image may be NSFW.
Clik here to view. - On the ‘Register New Plugin’ screen, select your assembly and select the class you want to register; I always choose to store my plug-ins in the database but this depends on your needs. Hit the “Register Selected Plugins” once you’re doneImage may be NSFW.
Clik here to view. - If everything is OK, you should see this kind of message:Image may be NSFW.
Clik here to view. - The next step is the registration of a new ‘Step’ which is the event the plug-in will be attached to; to register a new step for the new plug-in, select your plug-in in the right screen and click on the ‘Register New Step’ in the toolbar (or hit CTRL – T)Image may be NSFW.
Clik here to view. - Now this is the fun part: you have to tell the server to which event the plug-in will be attached to (Create, Update, Delete, etc.). You also need to specify on which entity the plug-in will be run and the stage of execution (pre or post): these parameters are mandatory! (You can find more information on the execution pipeline here and on plug-in development & deployment here) Image may be NSFW.
Clik here to view. - Hit ‘Register New Step’ to create the event handler
- Last step is to create a pre or post XML image depending on your needs: in my case, I always create a post image if I’m dealing with a ‘Create’ messages (obviously, there is nothing in the database at that time so a pre image is irrelevant) and I always create pre & post images on ‘Update’ messages to get the data before and after update (think audit plug-in for example). To create a new image, select the step you just created in the right screen and select the ‘Register New Image’ from the toolbar or hit CTRL – IImage may be NSFW.
Clik here to view. - In this last screen, you have to select the image type (pre or post) and give it a name: the name is really important if you want to use a code like the one below, which creates a new dynamic entity object from the post image:
// Post image for the current entity
DynamicEntity postImage = new DynamicEntity(); postImage = (DynamicEntity)context.PostEntityImages.Properties["postEntityImageXml"];
Image may be NSFW.
Clik here to view.
- Hit the ‘Register Image’ button to create the new image
- Once connected to the correct organization, the right screen will display the list of already deployed plug-ins Image may be NSFW.
- Everything is all set! Your plug-in is now deployed and ready to run Image may be NSFW.
Clik here to view.And here is the example based on the code above (see step 5 on this blog post):Image may be NSFW.
Clik here to view.
Links:
- Generating unique keys in C#: http://www.codeproject.com/KB/aspnet/UniqueKeys.aspx
- MSDN – Creating a simple plug-in: http://msdn.microsoft.com/en-us/library/bb955365.aspx