Источник:
http://blogs.msdn.com/crm/archive/20...utilities.aspx
==============
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.
- Using Visual Studio 2008, create a new Workflow Activity Library project targeting version 3.0 of the .NET Framework, and then do the following
- Digitally sign it
- Add references to the Microsoft Dynamics CRM SDK assembly files (located as part of the SDK download).
- Create a new class, and name it UrlBuilder.
- Replace the default code in the UrlBuilder class with the following code:
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(@"{0}", 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: }
- Create another new class, and name it FormatLineBreaks.
- Replace the default code in the FormatLineBreaks class with the following code:
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("Format Line Breaks", "Utilities")] 9: public partial class FormatLineBreaks : SequenceActivity 10: { 11: protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) 12: { 13: this.FormattedValue = (this.InputValue != null) ? this.InputValue.Replace("\n", "
") : 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: } 35: } 36: }
- Build the solution.
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!
- Download the tool if you don't already have it.
- Open the tool and create a connection to your CRM Web server and then connect to it.
- Select your organization and click Connect.
- Click Register, and then select Register New Assembly.
- In the Register New Plugin window, choose your compiled workflow utilities assembly.
- Leave the database option selected and click Register Selected Plugins.
- The tool will then register the assembly and provide a pop-up message if it was successful.
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.
- Create a new workflow rule for the Lead entity called New Lead Notification.
- Add a step, selecting the new Url Builder option step located in the Utilities group.
- Enter Url Builder as the step's description.
- Click Set Properties, and enter the correct URL to the Lead's edit page as the Value of the Url property. For example:
http:////sfa/leads/edit.aspx?id={0}
- Add a step, selecting the new Format Line Breaks option step located in the Utilities group.
- Enter Format Description as the step's description.
- Click Set Properties, and set the lead's description attribute.
- Add a new Send E-mail step and enter Send Alert E-mail for the description.
- Leave the Create New Message option selected, and click Set Properties.
- In the Send E-mail dialog box, configure the e-mail message, and in the body, add the new Url Builder and Format Line Breaks dynamic value.
- Save and publish your 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.
- I used Visual Studio 2008 to create my workflow assembly. You can also use Visual Studio 2005 to create a custom workflow assembly, but be sure to add the Windows Workflow Foundation framework first.
- Also check Nirav’s post about compiling the workflow activity with anycpu flag to provide the best compatibility between 32 and 64 bit environments.
- You can easily add additional utility classes to build out a useful library for your users.
- If you modify the assembly and register it again with your deployment, you may need to restart IIS and the AsyncService for your changes to take effect.
- A complete list of record URL’s are listed in the SDK, although you could just open a record in Internet Explorer to determine the correct link.
- For custom entities, your input URL would be something similar to: http:////userdefined/edit.aspx?etc=&id={0}. Be aware that the object type code can be different with each deployment to a new environment. You could extend this basic solution to use the MetadataService to find the correct object type code rather than having it hard coded.
- My example assumes that the URL you enter will be accessible to your users. If you use IFD with your deployment, you can either create proper domain mappings within your DNS to properly open the hyperlink. Or even simpler (although maybe a bit less elegant), you could create two instances of the UrlBuilder with two different URLs and set up two links in your e-mail messages...one for internal users and one for external users.
- You could consider wrapping the Send e-mail and the workflow assembly steps into a child workflow, which can then be reused within other workflow rules. Just remember to check the As a child workflow option before publishing.
- Finally, don't confuse the Create Record step (and selecting E-mail activity) with the Send E-mail step. If you use the Create Record step to create an E-mail activity, Dynamics CRM will create the e-mail activity but not actually send it. This approach is useful if you want a user to manually review or make alterations to the e-mail prior to sending. If you want the workflow rule to automatically send the e-mail, then be sure to choose the Send E-mail step.
Hopefully, this simple example demonstrates the ease by which a developer can enhance the native functionality of workflow.
Happy coding!
Jim Steger
Источник:
http://blogs.msdn.com/crm/archive/20...utilities.aspx