Custom Actions are lesser used processes than Workflows and Plugins in Dynamics 365, but very useful also at the same time. For people who have already have an idea of Custom Workflow Activity (or read my previous article), it’s going to be very easy. The coding part is the same, only "how we consume the code in Dynamics 365 process" is different, and use cases too, obviously. Custom Actions can be created with or without writing code, but they can be triggered only by the code. Here, we will write custom code to retrieve the case records assigned to calling users.
Step 1 - Create New Project
In Visual Studio, create a new project of type Class Library & select framework version 4.5.2. This might change for future versions. I have given the name as MyCasesAction, which tells the purpose of the workflow.
Step 2 - Add Required Packags
Go to Manage NuGet Packages and install Microssoft.CrmSdk.CoreAssemblies (for Microsoft.Xrm.Sdk namespace) & Microssoft.CrmSdk.Workflow (for Microsoft.Xrm.Sdk.Workflow namespace).
Step 3 - Create MyCasesAction Class
Create a class MyCasesAction inherited from CodeActivity. It will need to add System.Activities namespace.
- using System.Activities;
- namespace MyCasesAction {
- public class MyCasesAction: CodeActivity {
- protected override void Execute(CodeActivityContext context) {}
- }
- }
Step 4 - Adding Parameters
We will have 2 output parameters - one containing count of cases, the other having the name of cases separated by commas. We will take the user’s GUID from context.
- using Microsoft.Xrm.Sdk.Workflow;
- using System.Activities;
- namespace MyCasesAction {
- public class MyCasesAction: CodeActivity {
- [Output("Count of Cases")]
- public OutArgument < int > CaseCount {
- get;
- set;
- }
- [Output("Name of Cases")]
- public OutArgument < string > CaseNames {
- get;
- set;
- }
- protected override void Execute(CodeActivityContext context) {}
- }
- }
Step 5 - Adding Logic to Retrieve User Cases
- using Microsoft.Xrm.Sdk;
- using Microsoft.Xrm.Sdk.Query;
- using Microsoft.Xrm.Sdk.Workflow;
- using System.Activities;
- using System.Collections.Generic;
- namespace MyCasesAction {
- public class MyCasesAction: CodeActivity {
- [Output("Count of Cases")]
- public OutArgument < int > CaseCount {
- get;
- set;
- }
- [Output("Name of Cases")]
- public OutArgument < string > CaseNames {
- get;
- set;
- }
- protected override void Execute(CodeActivityContext context) {
-
- var workflowContext = context.GetExtension < IWorkflowContext > ();
- var serviceFactory = context.GetExtension < IOrganizationServiceFactory > ();
- var orgService = serviceFactory.CreateOrganizationService(workflowContext.UserId);
-
- var fetchXmlCurrentUserCases = @ " < fetch version = '1.0'
- output - format = 'xml-platform'
- mapping = 'logical'
- distinct = 'false' > < entity name = 'incident' > < attribute name = 'title' / > < filter type = 'and' > < condition attribute = 'ownerid'
- operator = 'eq-userid' / > < /filter> < /entity> < /fetch>";
-
- var cases = orgService.RetrieveMultiple(new FetchExpression(fetchXmlCurrentUserCases));
-
- if (cases == null || cases ? .Entities == null) return;
-
- var allCases = new List < string > ();
- foreach(var cs in cases.Entities)
- allCases.Add(cs["title"].ToString());
-
- CaseCount.Set(context, cases.Entities.Count);
-
- CaseNames.Set(context, string.Join(",", allCases.ToArray()));
- }
- }
- }
Step 6 - Signing the Assembly
In Dynamics 365, it is necessary to sign the assembly before registering. To do this:
- Right click on project, click on Properties to open.
- On the left pane, click on Signing.
- Check "Sign the assembly" checkbox.
- In "Choose a strong name key file" dropdown, click New…
- "Create Strong Name Key" popup will appear.
- Give some name.
- Optionally, you can protect this key file with a password.
- Click OK to generate the key and sign the assembly.
- Build the solution.
Step 7 - Register the Assembly in Dynamics 365
Open the Plugin Registration Tool and connect with your organization. If you don’t already have it, grab it by adding Microsoft.CrmSdk.XrmTooling.PluginRegistrationTool NuGet Package.
- Click on Register, then Register New Assembly.
- Register New Assembly popup will appear, select your project DLL from bin/debug folder of the project.
- After selecting DLL, make sure that the Select All is selected in Step 2.
- Leave the rest of the options as they are and click Register Selected Plugins, it should register your assembly successfully.
- You can verify the assembly after registering in Plugin Registration Tool.
Step 8 - Creating Custom Action in CRM and Consuming MyCasesAction
- Go to the Solution, create a new process, set name as “Get My Cases”, set category as “Action” & in the entity, I’m setting it as “None (global)”. If we will select some entity here, our action will get one default input parameter of the same type as given entity.
- Add two output arguments with the same type as output parameters given in MyCasesAction class. However, the names do not need to be the same but you can keep them the same to avoid confusion.
- Click on "Add Step" and look for your assembly; i.e MyCasesAction. Click on it and select MyCasesAction.MyCasesAction step.
- The step added from assembly will return case count and names, which should be set to output arguments. Add “Assign Value” step for both arguments.
- Click on “Set Properties” in Assign Value to set output argument value. Do it for both “CaseCount” & “CaseNames”.
- Save your process and click on “Activate” to activate it.
- It will ask for confirmation; click “Activate” to confirm.
Congratulations! You have successfully created Custom Action. Let’s test it now.
Step 9 - Testing Your Custom Action
As I mentioned above, Custom Actions can be triggered with code only. I will be using Dynamics 365 Console Caller to test our code, you can download this by following https://github.com/AshV/Dynamics365ConsoleCaller.
You need to grab Unique Name/Logical Name of your process, which is id new_GetMyCases in our case.
After downloading Dynamics 365 Console Caller open in Visual Studio and open Program.cs. Provide connection details & add code to test your custom action.
- using Microsoft.Crm.Sdk.Messages;
- using Microsoft.Xrm.Sdk;
- using System;
- using static System.Console;
- namespace Dynamics365ConsoleCaller {
- class Program
- {
- static void Main(string[] args) {
- IOrganizationService orgService = Connect.GetOrganizationService("[email protected]", "Your-Passowrd", "https://Org.crm.dynamics.com");
- Console.WriteLine("Connected to Organization Service!");
- ITracingService tracingService = Connect.GetTracingService("AshV_Log");
-
- var executeAction = orgService.Execute(new OrganizationRequest() {
- RequestName = "new_GetMyCases",
- });
- var caseCount = executeAction["CaseCount"];
- var caseNames = executeAction["CaseNames"];
- WriteLine($ "Count of Cases : {caseCount}");
- WriteLine($ "Name Cases : {caseNames}");
- }
- }
- }
Run the above code to test and verify your custom action.
Thanks for reading, I hope it’s helpful.