Tuesday, March 20, 2012

Auto number Plugin

Thanks to Atif for the inspiration




Heltall - whole number
En linje med tekst -single line of text


Open visual studio 2010
Create a new project for classlibrary


Add referenced to the below DLLs
microsoft.crm.sdk.proxy
microdsoft.xrm.sdk
System.Runtime.Serialization





You can find these dlls in the SDK\bin folder. Dowload the SDK from microsoft website



 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;


namespace AutoNumber
{
    public class AutoNumberPlugin : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            System.Threading.Mutex mtx = null;
            String debugText = "Inside Execute \n";
            try
            {
                Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)
                    serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));
                if (context.InputParameters.Contains("Target") &&
                context.InputParameters["Target"] is Entity)
                {
                    Entity entity = (Entity)context.InputParameters["Target"];
                    debugText = debugText + "Inside if loop - targe \n";

                    IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                    IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

                    string fetchXml = @"<fetch mapping='logical'>
                                                <entity name='ssb_autonumber'><all-attributes/>
                                                    <filter type=""and"">
                                                            <condition attribute=""ssb_entityname"" operator=""eq"" value='" + entity.LogicalName + "'" + " /></filter></entity></fetch>";


                    string mutextName = string.Format("{0}{1}", entity.LogicalName, "Autonumber");
                    mtx = new System.Threading.Mutex(false, mutextName);

                    mtx.WaitOne();

                    //get hold on the mutex and only release it after update was done ot the ssb_counter entity
                    // not sure if this will work in a multi server environment
                    debugText = debugText + "Before executing fetch \n";
                    EntityCollection result = service.RetrieveMultiple(new FetchExpression(fetchXml));
                    debugText = debugText + "After executing fetch \n";
                    string nextIncrementNumber = string.Empty;
                    if (result.Entities.Count == 1)
                    {
                        debugText = debugText + "inside the if loop - enitities \n";
                        //retrieve the counter
                        Entity autoNumber = result.Entities[0];
                        if (!autoNumber.Attributes.Contains("ssb_counter"))
                            throw new InvalidPluginExecutionException("ssb_counter must contain a value");
                        if (!autoNumber.Attributes.Contains("ssb_incrementunit"))
                            throw new InvalidPluginExecutionException("ssb_incrementunit must contain a value");
                        debugText = debugText + "get values \n";
                        int counter = Int32.Parse(autoNumber.Attributes["ssb_counter"].ToString());
                        int incrementUnit = Int32.Parse(autoNumber.Attributes["ssb_incrementunit"].ToString());
                        string prefix = autoNumber.Attributes.Contains("ssb_prefix") ? autoNumber.Attributes["ssb_prefix"].ToString() : string.Empty;
                        string prefixSeparator = autoNumber.Attributes.Contains("ssb_prefixseparator") ? autoNumber.Attributes["ssb_prefixseparator"].ToString() : string.Empty;
                        string suffix = autoNumber.Attributes.Contains("ssb_suffix") ? autoNumber.Attributes["ssb_suffix"].ToString() : string.Empty;
                        string suffixseparator = autoNumber.Attributes.Contains("ssb_suffixseparator") ? autoNumber.Attributes["ssb_suffixseparator"].ToString() : string.Empty;
                        string numberFormatter = autoNumber.Attributes.Contains("ssb_numberformatter") ? autoNumber.Attributes["ssb_numberformatter"].ToString() : string.Empty;
                        string fieldToUpdate;
                        if (autoNumber.Attributes.Contains("ssb_entityautonumberfield"))
                            fieldToUpdate = autoNumber.Attributes["ssb_entityautonumberfield"].ToString();
                        else
                            throw new InvalidPluginExecutionException("ssb_entityautonumberfield should not be emplty");
                        debugText = debugText + "before calling buld number \n";
                        nextIncrementNumber = BuildAutoNumber(prefix, prefixSeparator,
                            suffix, suffixseparator, counter, incrementUnit, numberFormatter);
                        debugText = debugText + "after calling build number \n" + nextIncrementNumber;
                        //increment the autonumber entity
                        //and update it to record the counter
                        debugText = debugText + "before calling update (autonumber)\n";
                        autoNumber.Attributes["ssb_counter"] = counter + incrementUnit;
                        service.Update(autoNumber);

                        debugText = debugText + "before calling update (entity) \n";
                        entity.Attributes.Add(fieldToUpdate, nextIncrementNumber);
                        //entity.Attributes[fieldToUpdate] = nextIncrementNumber;
                        // service.Update(entity);

                    }
                }
            }
            catch (Exception ex)
            {
                if (mtx != null)
                {
                    mtx.ReleaseMutex();
                    mtx = null;
                }

                // throw new InvalidPluginExecutionException("An error occured in Autonumber plugin", ex);
                throw new InvalidPluginExecutionException("An error occured in Autonumber plugin" + ex + "\n" + debugText);

            }
            finally
            {
                debugText = null;
                if (mtx != null)
                    mtx.ReleaseMutex();
            }
        }

        private string BuildAutoNumber(string prefix, string prefixSeparator, string suffix, string suffixSeparator, int counter, int incrementUnit, string numberFormatter)
        {
            bool hasPrefix = false, hasSuffix = false;

            string returnNumber = string.Empty;

            if (!string.IsNullOrEmpty(prefix))
            {
                hasPrefix = true;
            }
            if (!string.IsNullOrEmpty(suffix))
            {
                hasSuffix = true;
            }
            counter = counter + incrementUnit;
            returnNumber = (hasPrefix ? prefix + prefixSeparator : "") + counter.ToString(numberFormatter) + (hasSuffix ? suffixSeparator + suffix : "");


            return returnNumber;


        }
    }
}

Build your plugin
then use the plugin registration tool to register your plugin in the create event - preoperation step