Custom Workflow Activity in Microsoft Dynamics CRM 2011

Posted: October 14, 2012 in Code Snippets, CRM 2011

In my example, i’m going to create a custom workflow activity on case create. The workflow will send an email to team members and creates a task.

When ever a case gets created in CRM, I have a default team with some users in that. My goal is to send an email to all those users in the team.

Here im using early bound entities in my code to send an email. Add the Autogenerated cs file in your solution by generating it using crmsvcutil in the sdk bin folder.

1) Start Microsoft Visual Studio 2010.

2) On the File menu, click New, and then click Project.

3) In the New Project dialog box, select Workflow under Visual C# in the Installed Templates pane, and then select Activity Library.

4) Specify a name and location for the solution, and then click OK.

5) Navigate to the Project menu and select Properties. On the Application tab, specify .NET Framework 4 as the target framework.

6) Add references to the Microsoft.Xrm.Sdk.dll, Microsoft.Xrm.sdk.Workflow.dll, Microsoft.Crm.Sdk.Proxy, System.Runtime.Serialization assemblies.

7) Delete the Activity1.xaml file in the project.

8) Add a class file (.cs) to the project. In Solution Explorer, right-click the project, select Add, and then click Class. In the Add New Item dialog box, type a name for the class, and then click Add.

9) Make the class inherit from the CodeActivity.

10) Add functionality to the class by adding an Execute method:

In my CRM system i have a “Case Team A” with two users added in it.

Add the below code in your cs file.

namespace Workflow
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Messages;
    using Microsoft.Xrm.Sdk.Workflow;
    using Microsoft.Xrm.Sdk.Query;
    using System.Activities;
    using System.Web.Services.Protocols;
    using Microsoft.Crm.Sdk.Messages;
    using System.Diagnostics;

    public class CustomWorkflow : CodeActivity
    {
        [Input("Team Name")]
        [Default("Case Team")]
        public InArgument<string> CaseTeam { get; set; }

        [Output("Date time")]
        public OutArgument<DateTime> TaskDueDate { get; set; }

        protected override void Execute(CodeActivityContext executionContext)
        {
            try
            {
                // Create the tracing service
                ITracingService tracingService = executionContext.GetExtension<ITracingService>();

                // Create the context
                IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();

                IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();

                // Create the Organiztion service
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

                // Get the target entity from the context
                Entity target = (Entity)context.InputParameters["Target"];

                // Prepare DataContext by using AutoGenerated cs file
                XrmDataContext datacontext = new XrmDataContext(service);

                // Get the Team Name from the Workflow input parameter
                string teamName = CaseTeam.Get<string>(executionContext);

                // Get the Team Id from the Team Name
                var team = (from t in datacontext.TeamSet
                            where t.Name == teamName
                            select new { t.TeamId }).First();

                // Get all the members of the team to send email
                List<TeamMembership> teamMembers = (from t in datacontext.TeamMembershipSet
                                                    where t.TeamId == team.TeamId
                                                    select t).ToList();

                // Send email to memebers of the team
                CreateEmail(service, teamMembers, target, context.InitiatingUserId);

                // Set the Task DueDate to 2 days by using Output Parameter
                TaskDueDate.Set(executionContext, DateTime.Now.AddDays(2));

            }
            catch (SoapException ex)
            {
                // Add the SoapException message in event log
                EventLog.WriteEntry("code error", "Error occured in " + ex.Detail.InnerText.ToString(), EventLogEntryType.Error);
            }
            catch (Exception exe)
            {
                // Add the GeneralException message in event log
                EventLog.WriteEntry("code error", "Error occured in " + exe.InnerException.ToString(), EventLogEntryType.Error);
            }
        }

        public static void CreateEmail(IOrganizationService service, List<TeamMembership> teamMembers, Entity caseEntity, Guid loggedinUser)
        {
            // Create Email 
            Email email = new Email();

            // Set the from user of the email to Logged in user
            ActivityParty fromParty = new ActivityParty();
            fromParty.PartyId = new EntityReference(SystemUser.EntityLogicalName, loggedinUser);

            List<ActivityParty> toPartyList = new List<ActivityParty>();

            // Add the Activity party for each member in the team
            foreach (TeamMembership user in teamMembers)
            {
                ActivityParty toParty = new ActivityParty();
                toParty.PartyId = new EntityReference(SystemUser.EntityLogicalName, user.SystemUserId.Value);
                toPartyList.Add(toParty);
            }

            // Add the subject and description by concating the case ticket number
            email.Subject = "Case " + caseEntity.Attributes["ticketnumber"].ToString() + " Added. Please review";
            email.Description = "Case " + caseEntity.Attributes["ticketnumber"].ToString() + " Added. Please review";

            // Add To and From users to email
            email.To = toPartyList.ToArray();
            email.From = new[] { fromParty };

            // Set the case regarding
            email.RegardingObjectId = new EntityReference(Incident.EntityLogicalName, caseEntity.Id);

            // Create email
            Guid emailId = service.Create(email);

            SendEmailRequest sendRequest = new SendEmailRequest();
            sendRequest.EmailId = emailId;
            sendRequest.TrackingToken = string.Empty;
            sendRequest.IssueSend = true;

            // Send the email message.
            service.Execute(sendRequest);
        }
    }
}

Build the solution and Register the assembly using Plugin Registration tool

Then go to Processes under settings in crm2011 and add a workflow on case entity.

Click on Addstep and select your Workflow activity which you have previously registered using plugin tool. Remember to reset your iis or else you cant find your custom workflow activity.

Click on Set Properties and add the Input property in the textbox. In my example it
is “Case Team A”

After sending email i need to create a task. So i need to click on Add Step again and select Create Task

Here im going the set the Due Date of the Task by using Output Parameter in my Workflow
Click on Set Properties in Create Task and set the Due Date using Dynamic value as shown below

Once everything is done, Save the workflow and Activate it.

Now test your workflow by creating a case in your crm 2011. It should send an email to your case team users and create task with the due date set to 2days.

About these ads
Comments
  1. zahra says:

    Hi,
    I create a workflow in sdk but I don’t have the last submenu in “add step” named “workflow1.0.0.0″.why?

  2. akay says:

    You did not add the entites namespace in the code above.. Would it still work ?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s