-
Notifications
You must be signed in to change notification settings - Fork 15
Tutorial 5
PhuocLe edited this page Aug 26, 2018
·
10 revisions
- When lead created, send an email (with an email template) notification to all team members of the current user belong to teams
- Finish Tutorial 1: Plugin
- Finish Tutorial 2: Unit Test Plugin
- Finish Tutorial 3: WebResource
- Finish Tutorial 4: Unit Test WebResource
- A custom workflow get all team members of the current user belong to teams (Custom workflow:
RetrieveUsers
) - A custom workflow send email with email template for all team members of current record (Custom workflow
SendUsersMail
) - Create a
real-time workflow
whenLead create
and use 2 custom workflowRetrieveUsers
,SendUsersMail
- Add
New Project
04. C# Workflow Project
to solution.- A popup form
Add new Workflow Project
opened - Click button
><
to create/select a Dynamics 365 connection - After connected
PL.DynamicsCrm.DevKit
loaded all entities and bind to dropdownProject Name
- Checkbox
Others
should be checked - Keep the text box
Project Name
empty - Select
9.0.2.4
in theCrm Version
PL.DynamicsCrm.DevKit
get allMicrosoft.CrmSdk.CoreAssemblies
version fromNuGet
- Select
4.5.2
in the.Net version
- Click
OK
-
PL.DynamicsCrm.DevKit
created workflow project name:Paz.LuckeyMonkey.Workflow
- A popup form
- Rebuild solution to restore
NuGet
packages - Add
01. C# Late Bound Class
SystemUser
toEntities
folder ofPaz.LuckeyMonkey.Shared
project. If you don't know how, please check again the Tutorial 1: Plugin - Add
New Item
03. C# Workflow Class
toPaz.LuckeyMonkey.Workflow
project- A popup form opened
- Enter
RetrieveUsers
to texboxClass Name
- Click
OK
-
PL.DynamicsCrm.DevKit
created workflow class:RetrieveUsers
- Edit the
RetrieveUsers.cs
like bellow
public class RetrieveUsers : CodeActivity
{
[Output("UserIds")]
[RequiredArgument]
public OutArgument<string> UserIds { get; set; }
protected override void Execute(CodeActivityContext executionContext)
{
var workflowContext = executionContext.GetExtension<IWorkflowContext>();
var serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
var service = serviceFactory.CreateOrganizationService(workflowContext.UserId);
var tracing = executionContext.GetExtension<ITracingService>();
ExecuteWorkflow(executionContext, workflowContext, serviceFactory, service, tracing);
}
private void ExecuteWorkflow(CodeActivityContext executionContext, IWorkflowContext workflowContext, IOrganizationServiceFactory serviceFactory, IOrganizationService service, ITracingService tracing)
{
Debugger.Trace(tracing, "Begin Execute Workflow: RetrieveUsers");
//YOUR CUSTOM-WORKFLOW-CODE GO HERE
var fetchXml = $@"
<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true'>
<entity name='systemuser'>
<attribute name='systemuserid'/>
<link-entity name='teammembership' from='systemuserid' to='systemuserid' visible='false' intersect='true'>
<link-entity name='team' from='teamid' to='teamid' alias='aa'>
<link-entity name='teammembership' from='teamid' to='teamid' visible='false' intersect='true'>
<link-entity name='systemuser' from='systemuserid' to='systemuserid' alias='ab'>
<filter type='and'>
<condition attribute='systemuserid' operator='eq-userid'/>
</filter>
</link-entity>
</link-entity>
</link-entity>
</link-entity>
</entity>
</fetch>
";
var users = service.RetrieveAll<SystemUser>(fetchXml);
var userIds = string.Join(";",
users
.Where(u => u.Id != workflowContext.InitiatingUserId)
.Select(u => u.Id).Distinct().ToList());
UserIds.Set(executionContext, userIds);
Debugger.Trace(tracing, "End Execute Workflow: RetrieveUsers");
}
}
NOTED
Remember to use View-FetchXML to copy/paste code
- Open file
PL.DynamicsCrm.DevKit.Cli.json
by Notepad and edit these information in section:workflows.profile = "DEBUG"
workflows.solution = "LuckeyMonkey"
workflows.includefiles = "Paz.LuckeyMonkey.*.dll"
- Run
deploy.bat
of projectPaz.LuckeyMonkey.Workflow
- Add
New Item
03. C# Workflow Class
SendUsersMail
toPaz.LuckeyMonkey.Workflow
project - Edit code
SendUsersMail
like bellow
using System;
using System.Activities;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Sdk.Metadata.Query;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;
using Paz.LuckeyMonkey.Shared;
using Paz.LuckeyMonkey.Shared.Entities;
namespace Paz.LuckeyMonkey.Workflow
{
[CrmPluginRegistration("SendUsersMail", "SendUsersMail", "", "Paz.LuckeyMonkey.Workflow", IsolationModeEnum.Sandbox)]
public class SendUsersMail : CodeActivity
{
[Input("List UserIds")]
[RequiredArgument]
public InArgument<string> UserIds { get; set; }
[Input("Email Template Title")]
[RequiredArgument]
public InArgument<string> EmailTemplateTitle { get; set; }
[Input("Record Url")]
[RequiredArgument]
public InArgument<string> RecordUrl { get; set; }
protected override void Execute(CodeActivityContext executionContext)
{
var workflowContext = executionContext.GetExtension<IWorkflowContext>();
var serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
var service = serviceFactory.CreateOrganizationService(workflowContext.UserId);
var tracing = executionContext.GetExtension<ITracingService>();
ExecuteWorkflow(executionContext, workflowContext, serviceFactory, service, tracing);
}
private void ExecuteWorkflow(CodeActivityContext executionContext, IWorkflowContext workflowContext, IOrganizationServiceFactory serviceFactory, IOrganizationService service, ITracingService tracing)
{
Debugger.Trace(tracing, "Begin Execute Workflow: SendUsersMail");
//YOUR CUSTOM-WORKFLOW-CODE GO HERE
var templateId = GetTemplateId(executionContext, service);
if (templateId == Guid.Empty) return;
var objectId = GetRecordId(executionContext);
var objectType = GetEntityName(executionContext, service);
var request = new InstantiateTemplateRequest
{
TemplateId = templateId,
ObjectId = objectId,
ObjectType = objectType
};
var response = (InstantiateTemplateResponse)service.Execute(request);
if (response != null)
{
var email = new Email(response.EntityCollection[0]);
email.from = new List<ActivityParty>()
{
new ActivityParty { PartyId = new EntityReference(SystemUser.EntityLogicalName, workflowContext.InitiatingUserId) }
};
email.to = GetToEmail(executionContext);
email.RegardingObjectId = new EntityReference(objectType, objectId);
var emailId = service.Create(email.GetCreateEntity());
var sendRequest = new SendEmailRequest()
{
EmailId = emailId,
TrackingToken = $"[CRM-TRACKING]-{objectId}",
IssueSend = true
};
service.Execute(sendRequest);
}
Debugger.Trace(tracing, "End Execute Workflow: SendUsersMail");
}
private List<ActivityParty> GetToEmail(CodeActivityContext executionContext)
{
var userIds = UserIds.Get<string>(executionContext);
var rows = userIds.Split(";".ToCharArray());
var list = new List<ActivityParty>();
foreach (var row in rows)
list.Add(new ActivityParty { PartyId = new EntityReference(SystemUser.EntityLogicalName, Guid.Parse(row)) });
return list;
}
private Guid GetTemplateId(CodeActivityContext executionContext, IOrganizationService service)
{
var emailTemplateTitle = EmailTemplateTitle.Get<string>(executionContext);
var fetchData = new
{
title = emailTemplateTitle
};
var fetchXml = $@"
<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
<entity name='template'>
<attribute name='templateid'/>
<attribute name='createdon'/>
<order attribute='createdon' descending='true'/>
<filter type='and'>
<condition attribute='title' operator='eq' value='{fetchData.title}'/>
</filter>
</entity>
</fetch>
";
var rows = service.RetrieveAll<Template>(fetchXml);
if (rows.Count == 0) return Guid.Empty;
return rows[0].Id;
}
private Guid GetRecordId(CodeActivityContext executionContext)
{
var recordUrl = RecordUrl.Get<string>(executionContext);
string[] urlParts = recordUrl.Split("?".ToArray());
string[] urlParams = urlParts[1].Split("&".ToCharArray());
string objectTypeCode = urlParams[0].Replace("etc=", "");
var objectId = urlParams[1].Replace("id=", "");
return Guid.Parse(objectId);
}
public string GetEntityName(CodeActivityContext executionContext, IOrganizationService service)
{
var recordUrl = RecordUrl.Get<string>(executionContext);
string[] urlParts = recordUrl.Split("?".ToArray());
string[] urlParams = urlParts[1].Split("&".ToCharArray());
string objectTypeCode = urlParams[0].Replace("etc=", "");
var entityFilter = new MetadataFilterExpression(LogicalOperator.And);
entityFilter.Conditions.Add(new MetadataConditionExpression("ObjectTypeCode", MetadataConditionOperator.Equals, Convert.ToInt32(objectTypeCode)));
var entityQueryExpression = new EntityQueryExpression()
{
Criteria = entityFilter
};
var retrieveMetadataChangesRequest = new RetrieveMetadataChangesRequest()
{
Query = entityQueryExpression,
ClientVersionStamp = null
};
var response = (RetrieveMetadataChangesResponse)service.Execute(retrieveMetadataChangesRequest);
var entityMetadata = (EntityMetadata)response.EntityMetadata[0];
return entityMetadata.SchemaName.ToLower();
}
}
}
NOTED
You should add these 01. C# Late Bound Class
class: ActivityParty
, Email
, Template
to Entities
folder of Paz.LuckeyMonkey.Shared
project
- Run
deploy.bat
of projectPaz.LuckeyMonkey.Workflow
- Create an
email template type
:Lead
withTitle
:Lead - New Lead
- Create a
real-time workflow
nameLead - New Lead
to use 2 custom workflow - Check-in all files to your source control
- You finished this tutorial
This tutorial, you know howto
- Add
04. C# Workflow Project
- Add
03. C# Workflow Class
- Config
PL.DynamicsCrm.DevKit.Cli.json
forWorkflows