Monday, May 21, 2012

Integrating with Sharepoint

With the new built in integration of sharepoint list mode, crm offers the capability to integrate with sharepoint. However we are are often stuck with the builtin tool to create teh sharepoint folders which are not effective. So I am presenting a solution to automate the integration. In my previous post we have created a plugin to generate autonumber. We will use this to create the sharepoint folder.

Remember
1. Update the sharepoint site URL
2. If you want to use the defaults, update the GUID from your database
3. Remember to use the entity names as display names in sharepoint site

Assumption
1. Sharepoint site already created
2. Document libraries are created for each entity in CRM that integrated with sharepoint
(Created by default when you enable storing documents in shrepoint)


The below code will generate the sharepoint structure as below
spsite/entity/unique-identifier

If the folder already exists in sharepoint, it just links the folder in CRM else it creates the folder in Sharepoint and then created the document locations in CRM. You can customize in the code on which fileld to be used for the document location "GetSharepointAttribute(string EntityName)". Update this function to reflect your needs


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