Extending [Logical Users] list in Workflow
Hi guys,
Here is an example about how to call an assembly from the WF manager. This example deals with a request we had from a customer about how to extended the sendmail functionnality in order not to be limited by the [Logical User] list offered out of the box.
I have to thank Clint Warriner for his help about the logical implemention :-)
Here we go:
When you want to send an email via the Workflow manager inside your rule, you have the choice to select a particular recipient for your mails, or to choose the "Logical User" list, this list depends of the type of record you refer to.
Here is the list of "Logical User" listed for a case.
Here is the signification of the abover "Logical User" list:
[account/contact] Sends email to the account or contact associated with the case
[account] Sends email to the associated account for this case (customer field)
[contact] Sends email to the associated contact for this case (customer field)
[owner's manager] Sends email to the associated owner's manager of this case record.
[owner] Sends email to the associated Owner of the case record.
Here is bellow to which field these Logical Users refer to (in the Case Record):
The problem is:
What if I want to to something esle? Like:
=> Send the email to the Logical Account (customer in the TO: Line of my Email) and its Primary Contact in CC: Line ?
This is not possible in the regular workflow interface, so you need to develop you own SendMail Workflow Assembly and call it into workflow manager.
The code will:
- retrieve the customer properties (account), search for it's "PrimaryContact" property
- based on this, an EMail activity will be created with the Account (customer) in the TO Line and its primary contact in the CC Line
- then we send the email.
[note: we check the customer is an account (OTC =1) before trying to fill the CC line, we don't handle the situation where the Customer is a contact]
It's provided as is, there is no error handling at all, you will need to add the CrmSdkHelpers.Cs file provided by the CRM 3.0 SDK to do this:
using System;
using CrmSdk;
using SendMailToPrimaryContact.crmsdk;
namespace SendMailToPrimaryContact
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class MailToCustomer
{
public void CreateMailAndSendIt(Guid guidOfCustomer, int ObjectTypeCode)
{
// create CrmService instance
CrmService csvc = InitWebSvc();
// Create New EMAIL
email e =
new email();
e.ownerid = new Owner();
e.ownerid.type = EntityName.systemuser.ToString();
e.ownerid.Value = new Guid("302A6CD7-8E63-DA11-BC4B-0003FF0D54C9"); // to simplify things, we set static owner to admin...
e.subject = "A new case has been created (mail sent by custom DLL)"; // Email Subject
e.description = "Hi All, here is a new mail to notify you that a new case has been created"; // Email Body
// create an ActivityParty matching the customer guid to fill the TO line with....
activityparty ap = new activityparty();
ap.partyid = CrmSdk.CrmTypes.CreateLookup(EntityName.account.ToString(),guidOfCustomer);
// fill the TO Field with the customer....
e.to = new activityparty[]{ap};
// fill the CC Field with the primary contact of this customer....
if(ObjectTypeCode==1)
{
e.cc = new activityparty[]{RetrievePrimaryContact(guidOfCustomer)};
}
// Actually create the mail activity.
Guid emailid = csvc.Create(e);
// Send the mail.
SendMyMail(emailid);
// release resource.
csvc.Dispose();
}
public CrmService InitWebSvc()
{
CrmService csvc = new CrmService();
csvc.Credentials = System.Net.CredentialCache.DefaultCredentials;
csvc.PreAuthenticate = true;
csvc.UnsafeAuthenticatedConnectionSharing = true;
return csvc;
}
public void SendMyMail(Guid emailid)
{
// create CrmService instance
CrmService csvc = InitWebSvc();
// Send the Email based on the EmailId provided.
SendEmailRequest req = new SendEmailRequest();
req.EmailId = emailid;
req.TrackingToken = string.Empty;
req.IssueSend = true;
SendEmailResponse res = (SendEmailResponse)csvc.Execute(req);
// release ressource.
csvc.Dispose();
}
public activityparty RetrievePrimaryContact(Guid accountid)
{
// create CrmService instance
CrmService csvc = InitWebSvc();
// Creating ActivityParty matching the PrimaryContact
ColumnSet cs = new ColumnSet();
cs.Attributes = new string[]{"primarycontactid"};
activityparty ap = new activityparty();
Guid primarycontactGUID = ((account)csvc.Retrieve(EntityName.account.ToString(),accountid,cs)).primarycontactid.Value;
ap.partyid = CrmSdk.CrmTypes.CreateLookup(EntityName.contact.ToString(),primarycontactGUID);
// release ressource.
csvc.Dispose();
return ap;
}
}
}
Compile the code in Visual Studio 2003.
Now you have an Assembly DLL called: SendMailToPrimaryContact.dll
The name of your Class is: MailToCustomer()
The main method is: CreateMailAndSendIt()
Now you need to update your Workflow.Config file to handle your freshly created DLL:
Go to C:\Program Files\Microsoft CRM\Server\bin\assembly\ and Edit the Workflow.Config file
If the assembly is unsigned, you must add the allowunsignedassemblies attribute to the <workflow.config> element at the top of the Workflow.config file. Assign a value of "true" to the allowunsignedassemblies attribute. To update the Workflow.config file, use the following code sample.
<
method name="Send Mail to Customer When Case Created"
assembly="SendMailToPrimaryContact.dll"
typename="SendMailToPrimaryContact.MailToCustomer"
methodname="CreateMailAndSendIt"
group="Send Mail"
description="benlec">
<parameter name="Customer" datatype="lookup" entityname="account"/>
<parameter name="CustomerOTC" datatype="integer" default="0"/>
<result datatype="boolean"/>
</method>
Copy now SendMailToPrimaryContact.Dll into this directory too.
Now that you're done with the Config file and your DLL, create a MANUAL workflow rule which will call this assembly when a CASE is created.
Now you will need to setup the rule by specifying the 2 parameters we defined in the workflow config.
Here is what you have:
Double click on each parameter, select CustomerOTC static Value = 1, and Customer dynamic value = Account.
You should have something like this:
Click Save and Activate your rule.
Now when you create a case, and fill the customer field with your Account have a primary contact, click "More Actions" menu and apply the rule we created.
The Email created and sent shall look like this:
Hope this helps, here are some usefull things around this topic:
922607 How to use the Logical User fields in Microsoft Dynamics CRM 3.0 workflow rules
https://support.microsoft.com/default.aspx?scid=kb;EN-US;922607
Sending email via workflow as different user
https://blogs.msdn.com/crm/archive/2006/11/15/sending-email-via-workflow-as-different-user.aspx
Kind regards
Benjamin LECOQ
Comments
Anonymous
March 12, 2007
Hi Guys, More than only dealing with the Support Tools, I've just added a CRM SDK section to this blogAnonymous
March 21, 2007
Mmhhh, sweet, I'm loving it.Pretty cool way to demonstrate Workflow assembly 101.Great Post !Anonymous
August 14, 2007
Hi, I tried you code but i reseave an error regarding the CrmBoolean type.I add the CrmSdkHelpers.Cs file, but can't compile.ThanksAnonymous
August 30, 2007
The comment has been removedAnonymous
September 02, 2007
Hi Guys,Can you try to be precise with the Errors and exceptions you have?The code provided here does not handle any error, you need to modify it to dump the appropriate errors.Implement Try/Catch like this:try{ Guid emailid = csvc.Create(e);}catch(System.Web.Services.Protocols.SoapException ex){ Console.WriteLine(ex.Message + "." + ex.Detail.InnerText);}RegardsBenjaminAnonymous
September 03, 2007
Hello,The error is "Server was unable to process request..n0x80040217nThe specified object was not found.nPlatformn" could be something with the web services.I created a project and made a Web reference to the web-Services, the link is ok I already confirm, but when I invoke this method of a WS receive this error.The MSCRM is installed in other machine there is any problem with this? I read something about Remote connections or something like this…Thanks,JGCAnonymous
September 03, 2007
Hi Benjamin,Thanks for your help.the error is "Server was unable to process request..n0x80040217nThe specified object was not found.nPlatformn"ThanksAnaAnonymous
September 21, 2007
When I try to run the rule on a case I get this error in the event viewer Action {57EDFAE5-E567-DC11-920E-00010321C609} failed in step {55EDFAE5-E567-DC11-920E-00010321C609} of process instance {3C4E0294-E767-DC11-920E-00010321C609}. Please view the paused rule in the Microsoft.Crm.Workflow.Monitor for more information about the failure. When I look in the workflow monitor I see this error Error code =80070005 Access Denied. You do not have suffient access rights or priviliges to perform this action. I am logged in as administrator and restricted access is off for the admin user. Any help would be great. ThanksAnonymous
September 21, 2007
Try to run the Workflow Service under LocalSystem account....Anonymous
October 24, 2007
Hi, if I need to add the field CREATEDBY in the logical user list at workflow, I need to do this same dll?