Creating AutoNumber for Microsoft Dynamics CRM 4.0 using Plug-Ins with the help of FilteredView


Create two field as we created..

1) New_uniqueid ( Int)

2) New_id( nvarchar).

If you want AutoNumber as Int , no need to create two fields ,but we wanted AutoNumber as in specific format(OP/DEC08/0000000001) so we reqired to two field.

Steps for AutoNumber:

1) Retrieved the maximum number for entity based on field new_uniqueid.

2) Update both field new_uniqueid and new_id using web service on PostCreate event.

Source Code

using System;

using System.Collections.Generic;

using System.Text;

using System.Xml;

using System.Xml.Serialization;

using System.IO;

using System.Collections;

using Microsoft.Crm.Sdk;

using System.Data;

using System.Data.SqlClient;

using System.Web.Services.Protocols;

namespace CRM.PlugIn.UniqueIdGeneration

{

public class PlugInForUniqueId : IPlugin

{

string serverName = string.Empty;

string domain = string.Empty;

string authUser = string.Empty;

int leftPad;

string uniqueNoField=string.Empty;

string uniqueIdField=string.Empty;

static string logPath = string.Empty;

// get configuration string

public PlugInForUniqueId(string unsecure, string secureConfiguration)

{

XmlDataDocument doc = new XmlDataDocument();

doc.LoadXml(secureConfiguration);

// get database server name

XmlNode database = doc.SelectSingleNode(“//Database”);

serverName= database.InnerText;

// get domain name

XmlNode domainName = doc.SelectSingleNode(“//Domain”);

domain = domainName.InnerText;

// CRM User as Authentication User

XmlNode authUserName = doc.SelectSingleNode(“//AuthUser”);

authUser = authUserName.InnerText;

// get total no of digit for padding

XmlNode padding = doc.SelectSingleNode(“//Padding”);

leftPad=Convert.ToInt32( padding.InnerText);

// get FieldName and type of datatype should be Integer

XmlNode uniqueNo = doc.SelectSingleNode(“//UniqueNumber”);

uniqueNoField= uniqueNo.InnerText;

// get FieldName and type of datatype should be nvarchar

XmlNode Id = doc.SelectSingleNode(“//Id”);

uniqueIdField= Id.InnerText;

// get path of log file.

XmlNode Log = doc.SelectSingleNode(“//LogPath”);

logPath = Log.InnerText;

}

public void Execute(IPluginExecutionContext context)

{

// Create instance of Crm WenService

ICrmService Service = context.CreateCrmService(true);

string entityName = context.PrimaryEntityName;

string orgName = context.OrganizationName;

// Avialable max. number in database.

int maxUniqueNo = ReturnMaxNumber(serverName, entityName, orgName);

CrmNumber num = new CrmNumber();

num.Value = maxUniqueNo;

// Formatted Unique Id With entityname,month,year and unique No.

string formattedId = FormattedUniqueNumber(num.Value, context.PrimaryEntityName);

try

{

// DynamicEntity dyEntity = ReturnDynamicEntityToUpate(context, num);

if (context.InputParameters.Properties.Contains(“Target”))

{

DynamicEntity entity = (DynamicEntity)context.InputParameters.Properties[“Target”];

if (entity != null)

{

string entityId = context.PrimaryEntityName + “id”;

Guid id = (Guid)context.OutputParameters[ParameterName.Id];

DynamicEntity updateUniqueId = new DynamicEntity(context.PrimaryEntityName);

Key key = new Key(id);

KeyProperty keyProp = new KeyProperty(entityId, key);

updateUniqueId.Properties.Add(keyProp);

CrmNumberProperty propUniqueId = new CrmNumberProperty(uniqueNoField, num);

updateUniqueId.Properties.Add(propUniqueId);

StringProperty propFormattedId = new StringProperty(uniqueIdField, formattedId);

updateUniqueId.Properties.Add(propFormattedId);

Service.Update(updateUniqueId);

}

}

}

catch (SoapException SoapEx)

{

WriteLog(entityName, “On Create”,“ERROR”,SoapEx);

}

catch (Exception ex)

{

WriteLog(entityName, “On Create”, “ERROR”, ex.Message);

}

}

private int ReturnMaxNumber(string server, string entity, string orgName)

{

int maxNum = 0;

string dataSource = server;

string tableView = “Filtered” + entity;

string organizatioName = orgName ;

string databaseName = organizatioName + “_MSCRM”;

string sqlQuery = @” SETUSER ‘”+domain +“\\”+ authUser + “‘ select max(new_uniqueid) from “ + tableView ;

WriteLog(entity , “On Create”, “INFO”, “DatabaseServer :” + dataSource);

WriteLog(entity, “On Create”, “INFO”, “Sql Query :” + sqlQuery);

try

{

SqlConnection connection = new SqlConnection(“Data Source=” + dataSource + “;Initial Catalog=” + databaseName + “;Integrated Security=SSPI; Pooling=false”);

SqlCommand cmd = new SqlCommand(sqlQuery, connection);

connection.Open();

if (cmd.ExecuteScalar().ToString() != “”)

{

maxNum = Convert.ToInt32(cmd.ExecuteScalar());

}

connection.Close();

connection.Dispose();

if (maxNum > 0)

{

maxNum++;

}

else

{

maxNum = 1;

}

}

catch (SqlException sqlex)

{

WriteLog(entity, “On Create”, “ERROR”, sqlex);

maxNum =0;

}

return maxNum;

}

private string FormattedUniqueNumber(int num, string entity)

{

string finalUniqueNo=string.Empty;

try

{

DateTime currentDate = DateTime.Now;

string getMonth = currentDate.ToString(“MMM”).ToUpper();

string getYear = currentDate.Year.ToString().Substring(2, 2);

string numWithPad = num.ToString().PadLeft(leftPad, ‘0’);

string entiyName = entity.Substring(0, 2).ToUpper();

finalUniqueNo = entiyName + “/” + getMonth + getYear + “/” + numWithPad;

WriteLog(entity, “On Create”, “INFO”, “Unique ID=” + finalUniqueNo);

return finalUniqueNo;

}

catch (Exception ex)

{

WriteLog(entity, “On Create”, “ERROR”, ex.Message);

return finalUniqueNo;

}

}

private static void WriteLog(string Entity, string EventName, string MessageType, SoapException ex)

{

try

{

string lstrMessage;

TextWriter log = TextWriter.Synchronized(File.AppendText(logPath));

lstrMessage = Entity + ” | “ + EventName + ” | “ + MessageType + ” | “ + System.DateTime.Now.ToString () + ” | “ + ex.Detail.InnerXml;

log.WriteLine(lstrMessage);

log.Close();

}

catch (Exception ex1)

{

throw ex1;

}

}

private static void WriteLog(string Entity, string EventName, string MessageType, string Message)

{

try

{

string lstrMessage;

TextWriter log = TextWriter.Synchronized(File.AppendText(logPath));

lstrMessage = Entity + ” | “ + EventName + ” | “ + MessageType + ” | “ + System.DateTime.Now.ToString () + ” | “ + Message ;

log.WriteLine(lstrMessage );

log.Close();

}

catch (Exception ex)

{

throw ex;

}

}

private static void WriteLog(string Entity, string EventName, string MessageType, SqlException Message)

{

try

{

string lstrMessage;

TextWriter log = TextWriter.Synchronized(File.AppendText(logPath));

lstrMessage = Entity + ” | “ + EventName + ” | “ + MessageType + ” | “ + System.DateTime.Now.ToString() + ” | “ + Message ;

log.WriteLine(lstrMessage);

log.Close();

}

catch (Exception ex)

{

throw ex;

}

}

}

}

Now Register the Plug-In for any entity on PostCreate event.It will give the AutoNuber in this format(OP/DEC08/0000000001) I.e (first two character of Entity name/three character of current month+ two digit of current year/number with padding(10 digit but customizable))

Don’t forget to pass configuration string when registering Plug-In in Secure Configuration Field in this format

<Config><Database>Machine Name of Database</Database><Domain>Domain Name</Domain><AuthUser>Authenticated User of CRM on behalf of that query will be executed</AuthUser><Padding>number of character for padding </Padding><UniqueNumber>new_uniqueid</UniqueNumber><Id>new_id</Id><LogPath> Log path as D:\CRM\Logs\CrmLog.txt</LogPath></Config>

Using FilteredView to retrieve data in Plug-In or Callout


To retrieve data from CRM Database( FilteredView)…..

SqlConnection connection = new SqlConnection(“DataSource=<dsName>;Initial Catalog=<databaseName> ;Integrated Security=SSPI;”);

string sqlQuery = @” select max(new_uniqueid) from FilteredView” ;

SqlCommand cmd = new SqlCommand(sqlQuery, connection);

connection.Open();

 

/// Write Logic here

 

connection.Close();

 

But this code wasn’t returning any results .It was because callout/plugin run under the context of NT Authority\Network Service.

So we need to use impersonation in this case, for this we can use the following code .

SqlConnection connection = new SqlConnection(“DataSource=<dsName>;Initial Catalog=<databaseName> ;Integrated Security=SSPI; Pooling=false);

string sqlQuery = @” SETUSER ‘domainName\administrator’ select max(new_uniqueid) from FilteredView” ;

SqlCommand cmd = new SqlCommand(sqlQuery, connection);

connection.Open();

 

/// Write Logic here

 

connection.Close();

 

SETUSER To impersonate the admin who has access to the filtered views. More about SETUSER 

http://msdn.microsoft.com/en-us/library/ms186297.aspx

If we are not using Pooling=false in connection string its giving this error.

Event Log Error: The connection has been dropped because the principal that opened it subsequently assumed a new security context, and then tried to reset the connection under its impersonated security context…….

 

DynamicEntity Overview


A Dynamic Entity consists of a collection of strongly typed properties, much like a Property Bag. Dynamic Entities are used to develop against CRM entities and attributes that are not defined at design time.

When to use Dynamic Entities

 

Use the DynamicEntity class when writing code that must work on entities created after the code is deployed or with attributes added to entities after deployment

 

Example for accessing the accountid attribute using DynamicEntity.

 

dynamicEntity[“accounted”].Value.Value

 

The reason for the Value.Value is because dynEntity [“accountid”].value returns a Property object whose Value property points to the CRM Attribute type which in our case is Key. Key stores the GUID in its Value property.

 

Example of Using DynamicEntity for Create,Retrieve,Update,Delete.

 

Create DynamicEntity

 

DynamicEntity de = new DynamicEntity(“contact”);

StringProperty propFirstName = new StringProperty(“firstname”, “Arvind”);

de.Properties.Add(propFirstName);

StringProperty propLastName = new StringProperty(“lastname”, “Singh”);

de.Properties.Add(propLastName);

m_ID = Service.Create(de);

 

Retrieving a DynamicEntity

 

RetrieveRequest req = new RetrieveRequest();

req.ColumnSet = new AllColumns();

req.ReturnDynamicEntities = true;

TargetRetrieveDynamic target = new TargetRetrieveDynamic();

target.EntityName = “contact”;

target.EntityId = m_ID;

req.Target = target;

RetrieveResponse resp = (RetrieveResponse)service.Execute(req);

DynamicEntity de = (DynamicEntity)resp.BusinessEntity;

Key id = (Key)de.Properties[“contactid”] ;

string firstName = de.Properties[“firstname”].ToString();

string lastName = de.Properties[“lastname”].ToString();

 

Update using DynamicEntity

 

DynamicEntity de = new DynamicEntity(“contact”);

Key key = new Key(m_ID);

KeyProperty keyProp = new KeyProperty(“contactid”, key);

de.Properties.Add(keyProp);

StringProperty propFirstName = new StringProperty(“firstname”, “John”);

de.Properties.Add(propFirstName);

StringProperty propLastName = new StringProperty(“lastname”, “Smith”);

de.Properties.Add(propLastName);

Service.Update(de);

 

Delete

 

Service.Delete(“contact”, m_ID);

                       

%d bloggers like this: