Experience your
30 day trial
now!
GET STARTED
Today we welcome guest blogger Jim Steger, developer, blogger, and writer for Sonoma Partners with this guest post.
The new workflow functionality of Microsoft Dynamics CRM 4.0 opens new and exciting opportunities for developers and end users to easily create sophisticated business logic. However, sending alert-type e-mails is still one of the most common uses I see used for workflow. As you begin to work with CRM’s workflow e-mail capabilities, I hear two common requests frequently:
1. The ability to add a hyperlink URL to the body of a workflow generated e-mail message
2. Text in ntext fields do not display properly in an HTML email.
Unfortunately, neither of these requests works natively with CRM. In the case of #1, CRM does not surface the record id as a dynamic value, so you are unable to construct the URL properly in an e-mail.
With request #2, CRM doesn’t translate the ntext field into HTML. Take for example the following lead record. The text in the Description field is on 3 lines.
When a workflow e-mail is sent, the text in the Description field gets concatenated as seen in this example:
In this post, I demonstrate how you can solve both of the earlier requests to enhance the native Send E-mail workflow action using a very simple workflow assembly.
Creating the Workflow Utility Solution As many of you know by now, Microsoft based the Dynamics CRM 4.0 workflow on Windows Workflow Foundation (WF). This choice allows developers to easily create additional workflow logic to use within your CRM workflow rules.
Our workflow utilities solution will have two classes UrlBuilder and FormatLineBreaks. The UrlBuilder class simply creates an instance of the IContextService and then retrieves the current context. The context’s PrimaryEntityId property contains the record id that triggered the workflow. The code then simply appends the entity id to the inputted URL and formats it as a hyperlink. The code for FormatLineBreaks is even simpler…I simply replace any ASCII line breaks with an HTML break node.
Start by creating a basic workflow project which will contain your workflow activity classes. The CRM SDK, various books, and numerous blog posts describe this in better detail, so I will just walk you through the process quickly.
1: using System;
2: using System.Workflow.ComponentModel;
3: using System.Workflow.Activities;
4: using Microsoft.Crm.Workflow;
5:
6: namespace SonomaPartners.Crm.Workflow.Utilities
7: {
8: [CrmWorkflowActivity("Url Builder", "Utilities")]
9: public partial class UrlBuilder : SequenceActivity
10: {
11: // Override this method with our custom logic
12: protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
13: {
14: //Get context
15: IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
16: IWorkflowContext ctx = contextService.Context;
17:
18: // Get the record id from the context
19: Guid id = ctx.PrimaryEntityId;
20:
21: // Configure the Url and pass back to the output parameter
22: string fullUrl = string.Format(this.Url,id);
23: this.RecordUrl = string.Format(@"<a href=""{0}"">{0}</a>", fullUrl);
24:
25: return base.Execute(executionContext);
26: }
27:
28: // Allow the user to set the Url with this input parameter
29: public static DependencyProperty UrlProperty = DependencyProperty.Register("Url", typeof(string), typeof(UrlBuilder));
30: [CrmInput("Url")]
31: public string Url
32: {
33: get { return (string)base.GetValue(UrlProperty); }
34: set { base.SetValue(UrlProperty, value); }
35: }
36:
37: // Returns the formatted record Url to the workflow rule for use
38: public static DependencyProperty RecordUrlProperty = DependencyProperty.Register("RecordUrl", typeof(string), typeof(UrlBuilder));
39: [CrmOutput("RecordUrl")]
40: public string RecordUrl
41: {
42: get { return (string)base.GetValue(RecordUrlProperty); }
43: set { base.SetValue(RecordUrlProperty, value); }
44: }
45: }
46: }
8: [CrmWorkflowActivity("Format Line Breaks", "Utilities")]
9: public partial class FormatLineBreaks : SequenceActivity
11: protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
12: {
13: this.FormattedValue = (this.InputValue != null) ? this.InputValue.Replace("\n", "<br>") : string.Empty;
14: return base.Execute(executionContext);
15: }
16:
17: // Input value
18: public static DependencyProperty InputValueProperty = DependencyProperty.Register("InputValue", typeof(string), typeof(FormatLineBreaks));
19: [CrmInput("Input Value")]
20: public string InputValue
21: {
22: get { return (string)base.GetValue(InputValueProperty); }
23: set { base.SetValue(InputValueProperty, value); }
24: }
25:
26: // Returns the updated value
27: public static DependencyProperty FormattedValueProperty =
28: DependencyProperty.Register("FormattedValue", typeof(string), typeof(FormatLineBreaks));
29: [CrmOutput("Formatted Value")]
30: public string FormattedValue
31: {
32: get { return (string)base.GetValue(FormattedValueProperty); }
33: set { base.SetValue(FormattedValueProperty, value); }
34: }
36: }
Registering the Utilities Assembly Your workflow assembly is now ready for deployment. We use Ajith's free Plug-in Registration Tool to add the workflow assembly to our Dynamics CRM application. Don't worry that the name says plug-ins...it works for workflow assemblies as well!
Using the E-mail Utilities within Workflow User Interface Now that the custom solution is complete and registered with Microsoft Dynamics CRM, the next step is to use it in a workflow rule.
When a new lead is created, I will receive an alert e-mail that looks like this:
Additional Comments Here are some additional thoughts and tips to consider.
For custom entities, your input URL would be something similar to: http://<crmServer>/<organizationname>/userdefined/edit.aspx?etn=<entity name>&id={0}. Consider using the etn query string parameter instead of the etc (object type code), since the object type code on custom entities can vary between deployments.
Hopefully, this simple example demonstrates the ease by which a developer can enhance the native functionality of workflow.
Happy coding!
Jim Steger
PingBack from http://crmcourses.com/microsoft-dynamics-crm-team-blog-workflow-e-mail-utilities/
Thanks for sharing this information Jim. This is very helpful. I was wondering if we could attach files to these emails. Any pointers on this would be helpful.
Thanks,
Maruf
I am looking for a similar function, by attaching files, but I think the workaround, will be to:
1. Use SharePoint as a document repository
2. Link the file in the email to the SharePoint site
That would reduce the email overhead, and take advantage of the SharePoint versioning, and access rights if needed.
Hi All,
I have been using CRM 4 for my SaaS application. I need to send email using the from and to address from the custom entity i have created via workflow rule.
But currently it doesnt show the email attribute i have created.
Also is there a way to mention more than one email address for the "to" field.
I'm getting an error trying to register the assembly. The Plugin registration tool reports 1 assembly registered, 2 plugins encountered errors.
Here are the details:
Unhandled Exception: System.Web.Services.Protocols.SoapException: Server was unable to process request.
Detail: <detail><error>
<code>0x80044191</code>
<description>Assembly can not be loaded from C:\Program Files\Microsoft Dynamics CRM Server\server\bin\assembly\TestWorkflowActivityLibrary2.dll.</description>
<type>Platform</type>
</error></detail>
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at PluginRegistrationTool.CrmSdk.CrmService.Create(BusinessEntity entity) in D:\CRM 4.0\PluginRegistration\Web References\CrmSdk\Reference.cs:line 212
at PluginRegistrationTool.RegistrationHelper.RegisterPluginType(CrmOrganization org, CrmPlugin plugin) in D:\CRM 4.0\PluginRegistration\RegistrationHelper.cs:line 314
at PluginRegistrationTool.PluginRegistrationForm.btnRegister_Click(Object sender, EventArgs e) in D:\CRM 4.0\PluginRegistration\PluginRegistrationForm.cs:line 490
Can anyone help?
Thanks in advance!
Viktor
Let's say there is an nvarchar Attribute on an Entity, and that field is populated with a URL.
Also there is a fixed string that needs to be appended to this URL and then passed as a clickable URL on an e-mail.
Can this be accomplished using the method specified here? Or is there perhaps a better way?
Any help would be greatly appreciated.
The Above Example helps me a lot, but i have one query.
In the 4th step, where in you said,enter the correct URL to the Lead's edit page as the Value of the Url property. For example:
http://<crmserver>/<organization name>/sfa/leads/edit.aspx?id={0}
How is the id being used here. is it used as static or the id is being generated dynamically
Hi,
In the 4th step, where you are adding the lead page url, i see you are adding the url directly , is there any possiblity to add the GUID to it dynamically
How would you modify the above so that it could take another input parameter for the URL... so that rather than displaying the full hyper link it displays a text of your choice.
For Example,
Rather than http://www.myaddress.co.uk/fsfjosjs/fsljsflj
you get
Click Here (Dependant on input)
This comment is related to ntext fields in emails. The line feeds work if the email does not use an email template. Don't know if this was fixed through a rollup after this blog posted. In any case, it's nice to have this customer workflow step when you do in fact want to use an Email Template.
This is great. A huge problem that I can't get around is sending out from a CampaignResponse Email instead of Customer. In many instances, a campaign response may not be a lead and may just be a new reqistration from a web page hooked into the Campaign Response. I would like to send an email to the CampaignResponse email attribute rather than creating a Lead and adding the lead to the customer attribute and then use the customer to send from. Any suggestions? This would support the Event Accelerators.
Thank you.
mark.
Amazing. Just Amazing. Great article and Great Solution.
I actually have another way for doing this using Java-Scripting but this way is better. i will post mine soon.
Excellent article.
I actually have a question that pertains to this utility. How could one go about using the UrlBuilder for different environments (Dev, Test, and Production)? Right now, we are using the UrlBuilder in both Dev and Test, but since they are different environments, the Guid in the URL must be changed manually in the utility and saved for the URL to build correctly. Is there any way to create a workflow (or some other method) which will allow the UrlBuilder to generate different URLs, based on each environment? Thanks
I'm looking for a way to include a URL to a lead record in a workflow-generated email that is created when the lead is assigned to a user. The above looks ideal.
BUT
WIll it work with Dynamics CRM Online? It looks to me like the potential roadblock would be the step where I must register the assembly with the server.
I admit this procedure intimidates me, but I think I could manage it OK. I don't want to get halfway through though, and then discover I can't register the assembly because I'm using CRM online, rather than on-premise.
Steve