The Scenario
An organization has relationships with third-parties. Accounts, customers, members, suppliers etc. The organization has a SharePoint Web site and Dynamics CRM where the information about third-parties is processed. As the current business process dictates, large number of external clients - agents in this sample - needs to contact organization via email, fax, regular mail or in person in order to submit important business information - applications in this scenario. We will create a public SharePoint Web site where agents can submit applications and then those applications will be copied automatically to Dynamics CRM and when their processing in CRM is finished some feedback will be published back to the SharePoint Web site and agents will be able to see the status of the application in CRM online on the SharePoint Web site.
We defined the solution design as below:
In order to get the solution we defined the following tasks:
1. Develop a custom SharePoint Workflow which will search CRM for existing related entities and create them if necessary and then notify the client. In our case we will create contacts, tasks to process application form and email activities programmatically.
2. Develop a custom Web part which will display number of application forms in CRM posted from SharePoint Web site in the form of Key Performance Indicator – assume there is a target for number of application forms
Note:
You could reasonably ask the question why we are going to use SharePoint workflow, but not list event handlers or other types of custom applications which SharePoint platform allows us to use? The answer is that SharePoint workflows use Windows Workflow Foundation as a base and therefore we have all the advantages of this framework – persistence, tracking, flexibility at our hand. Also we can monitor these integration activities with the mighty tools I slightly described here
Solution
1. Custom SharePoint Workflow
1.1. Create a SharePoint Sequential Workflow project in Visual Studio
1.2. In the Code View of the Workflow create the following methods – SearchForContact, CreateContact, CreateTask, SendEmailToContact:
public Guid SearchForContact(string sFirstName, string sLastName, string sEmail)
{
Guid gResult = Guid.Empty;
try
{
QueryExpression queryContact = new QueryExpression();
queryContact.ColumnSet = new MyCRMService.AllColumns();
queryContact.EntityName = EntityName.contact.ToString();
queryContact.Criteria = new FilterExpression();
queryContact.Criteria.FilterOperator = LogicalOperator.And;
ConditionExpression Condition = new ConditionExpression();
Condition.AttributeName = "emailaddress1";
Condition.Operator = ConditionOperator.Equal;
Condition.Values = new object[] { sEmail };
ConditionExpression Condition1 = new ConditionExpression();
Condition1.AttributeName = "firstname";
Condition1.Operator = ConditionOperator.Equal;
Condition1.Values = new object[] { sFirstName };
ConditionExpression Condition2 = new ConditionExpression();
Condition2.AttributeName = "lastname";
Condition2.Operator = ConditionOperator.Equal;
Condition2.Values = new object[] { sLastName };
queryContact.Criteria.Conditions = new ConditionExpression[] { Condition, Condition1, Condition2 };
BusinessEntityCollection retrievedContacts = service.RetrieveMultiple(queryContact);
if (retrievedContacts.BusinessEntities.Length > 0)
{
gResult = ((contact)retrievedContacts.BusinessEntities[0]).contactid.Value;
}
}
catch (System.Web.Services.Protocols.SoapException soapex)
{
... // error handling
}
catch (Exception ex)
{
... // error handling
}
return gResult;
}
public Guid CreateContact(string sFirstName, string sLastName, string sEmail)
{
Guid gResult = Guid.Empty;
try
{
contact mycontact = new contact();
mycontact.firstname = sFirstName;
mycontact.lastname = sLastName;
mycontact.emailaddress1 = sEmail;
gResult = service.Create(mycontact);
}
catch (System.Web.Services.Protocols.SoapException soapex)
{
... // error handling
}
catch (Exception ex)
{
... // error handling
}
return gResult;
}
public Guid CreateTask(Guid gContactId)
{
Guid gResult = Guid.Empty;
try
{
task task = new task();
task.subject = ...;
task.regardingobjectid = new Lookup();
task.regardingobjectid.Value = gContactId;
task.regardingobjectid.type = EntityName.contact.ToString();
gResult = service.Create(task);
}
catch (System.Web.Services.Protocols.SoapException soapex)
{
... // error handling
}
catch (Exception ex)
{
... // error handling
}
return gResult;
}
public void SendEmailToContact(Guid gContactId)
{
try
{
activityparty recipient2 = new activityparty();
recipient2.partyid = new Lookup();
recipient2.partyid.type = EntityName.contact.ToString();
recipient2.partyid.Value = gContactId;
email email = new email();
email.subject = “Hello gorgeous”;
// just in case we would like to put some contact details into the email body, i.e. Dear firstname lastname,...
contact myContact = (contact)service.Retrieve(EntityName.contact.ToString(), gContactId, new AllColumns());
email.description = “Hello from our mighty SharePoint 2 CRM Integration”;
email.to = new activityparty[] { recipient2 };
SendEmailRequest req = new SendEmailRequest();
req.EmailId = service.Create(email); // here we create email programmatically
req.TrackingToken = string.Empty;
req.IssueSend = true;
try
{
SendEmailResponse res = (SendEmailResponse)service.Execute(req); // here we send email programmatically
}
catch (System.Web.Services.Protocols.SoapException er)
{
... // error handling
}
}
catch (System.Web.Services.Protocols.SoapException er)
{
... // error handling
}
}
1.3. Add Code Activity to the workflow design:
1.4. Generate an execute method for the Code Activity we have just created. In that method get values from the workflow associated SharePoint list item and execute our functions for CRM interaction:
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
try
{
// 1. parse SharePoint list item
string sFirstName = string.Empty, sLastName = string.Empty, sEmail = string.Empty;
try
{
sFirstName = this.workflowProperties.Item[this.workflowProperties.Item.Fields["First name"].InternalName].ToString();
sLastName = this.workflowProperties.Item[this.workflowProperties.Item.Fields["Last name"].InternalName].ToString();
sEmail = this.workflowProperties.Item[this.workflowProperties.Item.Fields["Email address"].InternalName].ToString();
}
catch (Exception ex)
{
... // error handling
}
// 2. search for existing contact - First Name, Last Name, Email
Guid gCntactId = SearchForContact(sFirstName, sLastName, sEmail);
// 2.1. does not exist – create
if (gCntactId == Guid.Empty)
{
gContactId = CreateContact(sFirstName, sLastName, sEmail);
}
if (gContactId != Guid.Empty)
{
// 3. Create task and send email to contact
Guid gTaskId = CreateTask(gContactId);
SendEmailToContact(gContactId);
}
}
catch (Exception ex)
{
... // error handling
}
}
1.5. Build workflow project, deploy it to the SharePoint Web site
1.6. Create a SharePoint list with the following columns:
1.7. Associate workflow with the list or library you created, create new record and see how your SharePoint 2 CRM integration works. :)
That’s it for now. Please stay tuned for the part number 2 of the proposed solution – Key Performance Indicator Web part for Dynamics CRM.
An organization has relationships with third-parties. Accounts, customers, members, suppliers etc. The organization has a SharePoint Web site and Dynamics CRM where the information about third-parties is processed. As the current business process dictates, large number of external clients - agents in this sample - needs to contact organization via email, fax, regular mail or in person in order to submit important business information - applications in this scenario. We will create a public SharePoint Web site where agents can submit applications and then those applications will be copied automatically to Dynamics CRM and when their processing in CRM is finished some feedback will be published back to the SharePoint Web site and agents will be able to see the status of the application in CRM online on the SharePoint Web site.
We defined the solution design as below:
In order to get the solution we defined the following tasks:
1. Develop a custom SharePoint Workflow which will search CRM for existing related entities and create them if necessary and then notify the client. In our case we will create contacts, tasks to process application form and email activities programmatically.
2. Develop a custom Web part which will display number of application forms in CRM posted from SharePoint Web site in the form of Key Performance Indicator – assume there is a target for number of application forms
Note:
You could reasonably ask the question why we are going to use SharePoint workflow, but not list event handlers or other types of custom applications which SharePoint platform allows us to use? The answer is that SharePoint workflows use Windows Workflow Foundation as a base and therefore we have all the advantages of this framework – persistence, tracking, flexibility at our hand. Also we can monitor these integration activities with the mighty tools I slightly described here
Solution
1. Custom SharePoint Workflow
1.1. Create a SharePoint Sequential Workflow project in Visual Studio
1.2. In the Code View of the Workflow create the following methods – SearchForContact, CreateContact, CreateTask, SendEmailToContact:
public Guid SearchForContact(string sFirstName, string sLastName, string sEmail)
{
Guid gResult = Guid.Empty;
try
{
QueryExpression queryContact = new QueryExpression();
queryContact.ColumnSet = new MyCRMService.AllColumns();
queryContact.EntityName = EntityName.contact.ToString();
queryContact.Criteria = new FilterExpression();
queryContact.Criteria.FilterOperator = LogicalOperator.And;
ConditionExpression Condition = new ConditionExpression();
Condition.AttributeName = "emailaddress1";
Condition.Operator = ConditionOperator.Equal;
Condition.Values = new object[] { sEmail };
ConditionExpression Condition1 = new ConditionExpression();
Condition1.AttributeName = "firstname";
Condition1.Operator = ConditionOperator.Equal;
Condition1.Values = new object[] { sFirstName };
ConditionExpression Condition2 = new ConditionExpression();
Condition2.AttributeName = "lastname";
Condition2.Operator = ConditionOperator.Equal;
Condition2.Values = new object[] { sLastName };
queryContact.Criteria.Conditions = new ConditionExpression[] { Condition, Condition1, Condition2 };
BusinessEntityCollection retrievedContacts = service.RetrieveMultiple(queryContact);
if (retrievedContacts.BusinessEntities.Length > 0)
{
gResult = ((contact)retrievedContacts.BusinessEntities[0]).contactid.Value;
}
}
catch (System.Web.Services.Protocols.SoapException soapex)
{
... // error handling
}
catch (Exception ex)
{
... // error handling
}
return gResult;
}
public Guid CreateContact(string sFirstName, string sLastName, string sEmail)
{
Guid gResult = Guid.Empty;
try
{
contact mycontact = new contact();
mycontact.firstname = sFirstName;
mycontact.lastname = sLastName;
mycontact.emailaddress1 = sEmail;
gResult = service.Create(mycontact);
}
catch (System.Web.Services.Protocols.SoapException soapex)
{
... // error handling
}
catch (Exception ex)
{
... // error handling
}
return gResult;
}
public Guid CreateTask(Guid gContactId)
{
Guid gResult = Guid.Empty;
try
{
task task = new task();
task.subject = ...;
task.regardingobjectid = new Lookup();
task.regardingobjectid.Value = gContactId;
task.regardingobjectid.type = EntityName.contact.ToString();
gResult = service.Create(task);
}
catch (System.Web.Services.Protocols.SoapException soapex)
{
... // error handling
}
catch (Exception ex)
{
... // error handling
}
return gResult;
}
public void SendEmailToContact(Guid gContactId)
{
try
{
activityparty recipient2 = new activityparty();
recipient2.partyid = new Lookup();
recipient2.partyid.type = EntityName.contact.ToString();
recipient2.partyid.Value = gContactId;
email email = new email();
email.subject = “Hello gorgeous”;
// just in case we would like to put some contact details into the email body, i.e. Dear firstname lastname,...
contact myContact = (contact)service.Retrieve(EntityName.contact.ToString(), gContactId, new AllColumns());
email.description = “Hello from our mighty SharePoint 2 CRM Integration”;
email.to = new activityparty[] { recipient2 };
SendEmailRequest req = new SendEmailRequest();
req.EmailId = service.Create(email); // here we create email programmatically
req.TrackingToken = string.Empty;
req.IssueSend = true;
try
{
SendEmailResponse res = (SendEmailResponse)service.Execute(req); // here we send email programmatically
}
catch (System.Web.Services.Protocols.SoapException er)
{
... // error handling
}
}
catch (System.Web.Services.Protocols.SoapException er)
{
... // error handling
}
}
1.3. Add Code Activity to the workflow design:
1.4. Generate an execute method for the Code Activity we have just created. In that method get values from the workflow associated SharePoint list item and execute our functions for CRM interaction:
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
try
{
// 1. parse SharePoint list item
string sFirstName = string.Empty, sLastName = string.Empty, sEmail = string.Empty;
try
{
sFirstName = this.workflowProperties.Item[this.workflowProperties.Item.Fields["First name"].InternalName].ToString();
sLastName = this.workflowProperties.Item[this.workflowProperties.Item.Fields["Last name"].InternalName].ToString();
sEmail = this.workflowProperties.Item[this.workflowProperties.Item.Fields["Email address"].InternalName].ToString();
}
catch (Exception ex)
{
... // error handling
}
// 2. search for existing contact - First Name, Last Name, Email
Guid gCntactId = SearchForContact(sFirstName, sLastName, sEmail);
// 2.1. does not exist – create
if (gCntactId == Guid.Empty)
{
gContactId = CreateContact(sFirstName, sLastName, sEmail);
}
if (gContactId != Guid.Empty)
{
// 3. Create task and send email to contact
Guid gTaskId = CreateTask(gContactId);
SendEmailToContact(gContactId);
}
}
catch (Exception ex)
{
... // error handling
}
}
1.5. Build workflow project, deploy it to the SharePoint Web site
1.6. Create a SharePoint list with the following columns:
1.7. Associate workflow with the list or library you created, create new record and see how your SharePoint 2 CRM integration works. :)
That’s it for now. Please stay tuned for the part number 2 of the proposed solution – Key Performance Indicator Web part for Dynamics CRM.
Comments
Post a Comment