With
the new release of Microsoft Dynamics CRM, version 2011, was introduced a new
concept: the Dialogs. Similar to the workflows, Dialogs are processes that
guide users through a series of steps in an automatic and consistent way, but
in a wizard-like style.
In
some way we can assert that Dialogs are the synchronous and interactive version
of workflows.
Dialogs
are especially suitable in situations where a user needs to follow a
consistent, rigid and standardized process that necessitates user input based on
questions and answers and the flow decisions are made automatically upon them
in the background; obviously, in this way, the organization’s productivity and
its effectiveness are increased, with an important reduction in error
possibility.
Imagine,
for example, how dialogs could expedite phone calls in a call or customer care
center. Highly skilled or technical staff need not be involved in a high
percentage of cases. In fact, Dialogs can be used to guide less-experienced
employees in troubleshooting, or in information gathering processes with
minimal effort and training.
Furthermore,
messages and services can be personalized, resulting in a major differentiator
and a competitive advantage.
I've done a depth study and analysis of the Microsoft Dynamics CRM 2011 Dialogs. Dialogs offer a very powerful tool to design consistent, rigid, standardized and interactive processes but have some limitations that we examined and analyzed and that we discuss in this paper, along with some custom solutions we have designed to try to work around.
Components of Dialog Pages
Before
we explain the layout components of dialogs, it's very important you to
understand that page layouts are neither configurable nor customizable.
Dialogs that are created or updated
outside of Microsoft Dynamics CRM by creating or updating the underlying XAML
file are not supported in Microsoft Dynamics CRM.
Dialog
pages components are:
-
Page Header
-
Prompt and Response
-
Tip Text
-
Comments
The
following figure shows these sections in a dialog page:
This
section displays the dialog process name along with the page name. The messages
in this section are configurable.
There
is no automatic page number but it's a helpful practice to enter the page
number as part of the title.
Each
dialog page must have at least one prompt and response area. Pages can have
more than one but using too many will mean the user must scroll through the
pages and make it difficult to read.
Responses
allow users to enter information but entries are not required for each prompt.
Through
some experimentation, I have found a solution to make prompt messages (and
tips) configurable, avoiding the user to must to work directly on the dialog
definition to change them.
The
solution is based upon the use of the dynamic values and the CRM custom
entities and it is explained below.
1.
Create a custom entity in MS Dynamics CRM
with a number of fields depending on how many custom prompt and tips messages
we need. The type of these fields must, obviously, to be "text" and
the length depends from what is predicted may be the maximum message length.
2.
Consider that we need to create a custom
entity for each process and must to exist one and only one record of this
entity that contains all the needed messages.
3.
Then, create a one to many relationship
between this entity and the entity involved in the dialog process.
4.
Next, create a record of the custom entity
entering all the messages in the appropriate fields.
5.
At this point, all records of the entity
involved in the dialog process must be associated with the newly created
record. Develop a plugin to make that association for every new record created.
For those that already exist in the system, instead of doing this association
manually, it is better to develop an automated process.
Now
it's possible to enter dynamic value for each prompt message, retrieving it
from the appropriate record field and dialog message are configurable, in fact,
it's sufficient for a user update the appropriate message from the
configuration record created to modify a prompt or a tip message in a dialog
page without the need to change it directly into the dialog definition. This
solution also works for page titles.
This
section is useful to display instructions that are not included in the prompt
message. Every prompt can have a separate tip associated to it and it will be
displayed when the user enter with the mouse on it.
This
area it is very useful because entered information persist throughout the
dialog process, making it possible to write information on one page that is
needed in another subsequent.
Buttons
Buttons
displayed in each dialog page are:
-
Help – Leads the user to the Microsoft
Dynamics CRM help page.
-
Summary – Displays the dialog session.
-
Previous – Returns the user to the previous
dialog page. This option is only available if the user has proceeded to another
page next the first.
-
Next – Advances the user to the next dialog
page. This option is hidden when the user has proceeded to the last page of the
dialog session.
-
Finish - Exits the dialog pages. This
option only displays when the user has reached the final step of the dialog
session.
-
Cancel - Cancels the dialog session before
the user has reached the end of the dialog process. When this button is
selected, the dialog session will be closed with a Status Reason of Canceled.
Important:
it’s not possible to neither customize these buttons nor change their behavior
programmatically (i.e.: show/hide).
A
dialog process can be started in one of the following ways:
1.
Manually.
2.
Automatically, as a child process of
another dialog.
3.
Calling by its URL.
It’s
important to you to understand that, due to its interactive nature, it's neither
contemplated a way to start a dialog process using the SDK nor from another
kind of process such as a workflow.
Due to the interactive nature of the
dialog process, you cannot run a dialog using the Microsoft Dynamics CRM SDK. A
dialog can only be run through the Microsoft Dynamics CRM Web application and is
not supported in Microsoft Dynamics CRM for Microsoft Office Outlook with
Offline Access.
For
the same reasons a Dialog cannot be triggered by events; it always runs
on-demand. Dialogs always require user interaction to complete. Furthermore Dialogs
can only be run on one record at a time.
All
dialog processes are associated with a URL, hence you can call them by using
its URL.
To
open a dialog through its URL you need the following:
1.
The unique identifier for the dialog.
2.
The logical name for the entity the dialog
is created for.
3.
The unique identifier for the record you
want to have the dialog run against.
The
URL is formatted as below:
[organization
url]/cs/dialog/rundialog.aspx?
DialogId=[dialog
unique identifier]&
EntityName=[entity
logical name]&
ObjectId=[unique
identifier for the record]
To get the unique identifier for the
dialog, navigate to Settings, and in the Process Center group, select
Processes. Right click the dialog, and in the context menu, select Copy a Link.
This
feature is useful because it allows to externally calling the dialog process.
To retrieve the needed information to build the URL from CRM it is necessary to
develop a Workflow utility, because creating a link to a Microsoft Dynamics CRM
record is not available out of the box.
Remember
that there is no a way to pass parameters to the dialog process not even
through its URL.
The
following options are provided natively by Microsoft Dynamics CRM for setting
up dialog process steps:
1.
Stage
2.
Page
3.
Prompt and Response
4.
Check Condition
5.
Conditional Branch
6.
Default Action
7.
Query CRM Data
8.
Assign Value
9.
Create Record
10. Update
Record
11. Assign
Record
12. Send
E-Mail
13. Start
Child Workflow
14. Link
Child Dialog
15. Change
Status
16. Stop
Dialog
Most
of these actions are self-explanatory and well documented, but I want discuss
"Link Child Dialog" and "Start Child Workflow".
Link Child Dialog
A
dialog process can call a child dialog. The child dialog must be associated with
the primary entity of the dialog process or a related entity. The "Link
Child Dialog" action allows you to pass data by using input arguments.
Note again that input arguments and parameters are not available for the
primary dialog process and the child dialog must to be marked as such during
the creation step.
There
is a big limit to consider:
Link child dialog cannot be an
intermediate step.
It
means that, in this release, "Link Child Dialog" must to be the last
step of the process. Furthermore, it can be only one child dialog per dialog
process.
An
important feature is the ability to create a recursive process using "Link
Child Dialog" step. I used this feature to try to achieve a solution to a
problem that I'll show later.
Similarly
to "Link Child Dialog" action, only workflow processes that are
configured to run as child processes can be run from a dialog session and,
furthermore, it must be associated to the primary or a related entity of the
dialog process.
This
is an important feature that allows us to start some processes in the
background, passing them any needed data as input parameters.
It's
possible, for example, collect some data from the dialog and then start some
processes that will operate on that data.
Remember
that unlike the dialogs, workflows are asynchronous processes and hence, they
run separate from the caller dialog. Therefore, never develop a dialog step
conditioned to a workflow output.
A
loop action is not available for the dialog processes steps. That means that
you cannot use a "while-action" to do the same interactive actions
repetitively.
However
it's possible to simulate a loop by using recursion on child dialog. Simply
call "Link Child Dialog" to itself until the termination condition is
reached.
This
could be a very useful feature but, unfortunately, as I mentioned early, there
is the one child per process limitation and this must be the last step of the
process.
I
used this feature to solve a problem that I will show later but these
limitations make it less flexible and thus poorly serviceable.
A
very powerful feature is the ability to extend the native actions of the
dialogs with custom workflow activities.
Important
to know: The only one supported framework is Windows Workflow Foundation 4.0,
therefore custom activities must be developed using this and not the 3.5 version.
Writing
custom workflow activities gives you the power to develop all the needed
business logic by using the SDK. By properly using InArgument and OutArgument
you can pass data to the activities and receive data from them.
To
develop custom workflow activities and make them available to Dynamics CRM
Dialogs, you must to create an "Activity Library" project within
Visual Studio 2010, then check that the framework version is 4.0 and that the
framework-type is “.NET framework” and not “.NET framework client profile”
(often it is the default setting).
The
following assemblies are needed hence add a reference to them:
·
microsoft.xrm.sdk.dll
·
microsoft.xrm.sdk.workflow.dll
These
are distributed with the Microsoft Dynamics CRM 2011 SDK.
Each
custom workflow activity developed must derive from System.Activities.CodeActivity
and require the following namespaces:
·
Microsoft.Xrm.Sdk
·
Microsoft.Xrm.Sdk.Workflow
Each
parameter needed as input must:
1.
Be an InArgument<T>, where T is the
type.
2.
Use [Input(InputName)] attribute, where
"InputName" is a string and it is the name displayed in the dialog
step properties window.
3.
Use [Default("DefaultValue")]
attribute, where "DefaultValue" is the default value that we want for
the parameter.
Although
the default value is not required, it's better to use it, even empty, because
the absence of it could cause problems during the library registration process.
Each
parameter needed as output must:
1.
Be an OutArgument<T>, where T is the
type.
2.
Use [Output(OutputName)] attribute, where
"OutputName" is a string and it is the name displayed in the dialog
step properties window.
After
that, you must to override the Execute() method in which you write your
business logic.
Below
a skeleton of a Custom Workflow Activity that follow the above rules.
using System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Activities;
using
Microsoft.Xrm.Sdk;
using
Microsoft.Xrm.Sdk.Workflow;
namespace
CustomWorkflowActivitiesNamespace
{
public sealed class SkeletonCustomActivity
: CodeActivity
{
[Input("Input Argument 1")]
[Default("")]
public InArgument<string>
InputArgument1 { get; set; }
[Input("Input Argument 2")]
[Default("")]
public InArgument<string>
InputArgument2 { get; set; }
[Output("Output Argument")]
public OutArgument<bool>
OutputArgument { get; set; }
protected override void
Execute(CodeActivityContext context)
{
//Put your logic here
}
}
Input Validation
Unfortunately, there is no a way to
validate the input data entered by a user native in the dialogs processes.
In an attempt to find a solution to this
problem, I have tried to exploit all the features available.
I have designed and experimented two
solutions but, unluckily, both have some limits
1.
Using of
custom workflow activity
2.
Using of
custom workflow activity, Link Child Dialog action and recursion
Exploiting the advantages and the features
of the custom workflow activity, I have designed a generic activity that
carries out data validation based upon regular expressions. With the regular
expressions we can make a different kind of validation, covering a high
percentage of situations and therefore the module is highly reusable.
public sealed
class RegularExpressionValidator : CodeActivity
{
[Input("String to Validate")]
[Default("")]
[RequiredArgument]
public InArgument<string>
StringToValidate { get; set; }
[Input("Regular Expression")]
[Default("")]
public InArgument<string>
RegularExpression { get; set; }
[Output("Input String is Valid")]
public OutArgument<bool> InputStringIsValid
{ get; set; }
protected override void
Execute(CodeActivityContext context)
{
bool _inputStringIsValid =
Regex.IsMatch(StringToValidate.Get(context),RegularExpression.Get(context));
InputStringIsValid.Set(context, _inputStringIsValid);
}
Validation using Custom Workflow Activity
By using a custom workflow activity that performs
the validation of an input (such as that above), we insert this after the
"prompt and response" step that needs a validation, passing the user
input data as input argument. Then execute the business logic to perform the
validation and retrieve the result boolean value returned as output argument.
Next we use that value in a check condition step
and, if the input was invalid, display a message error to the user in the next
page.
As I mentioned early, there is no way to inhibit
the dialog buttons, therefore, with this solution you can only inform the user
about the invalid data entered, but you cannot prevent him from going to the
next step, therefore, it's up to the user to go to the previous page and
correct the error.
This solution is based on the features, concepts
and custom solutions described above.
Conceptually, you use a custom activity to
perform data validation and the recursion to simulate a loop. In this
"virtual loop" you are asking the user to input data, check its
validity and proceed to next step or display an error message and asking to
reenter the correct data, according to the result of the validation check.
Below a schema to set up this solution:
1.
Create a
Dialog and mark it as a Child.
2.
In the dialog
created in step 1 insert a step to ask for user data input.
3.
Insert a next
step with the data validation activity.
4.
Insert a
Check Condition to verify the validation result.
a.
If the data
are not valid recursively call itself.
b.
If the data
are valid add a Stop Dialog action to terminate recursion.
As already explained, use of Link Child Dialog
action has two big limitations:
1.
There is a
maximum of one "Link Child Dialog" action per dialog process.
2.
This action
must be the last of the process.
These restrictions have strong implications:
1.
All the
validation logic must be done in one unique "Link Child Dialog"
action.
2.
It must be
the last step of the dialog process.
Although it could be technically achievable in
many casuistries, it forces the functional process to be adapted to those
conditions and it's unacceptable: the technology must to adapt to the
functional requisites and the processes and not the vice versa.
External information as necessary input for the
process
You might encounter situations in which there is
the need of some external information already available at the beginning of a
dialog process.
Although there is no a way to pass arguments,
you can work around this limit using custom workflow activities. You can easily
develop an activity that retrieves all the needed information and insert it as
first step of the process, before every other prompt and response.
Obviously, this workaround works well also for
every intermediate process step where there is the need of external
information, meaning not provided by the user.
A very powerful and useful feature provided by
Microsoft Dynamics CRM 2011 is the ability to monitor the dialog processes.
The dialog process record contains a Dialog
Sessions link that lists all executed instances of that process in the system
with their status.
Status can be one of the following:
·
In Progress
·
Canceled
·
Completed
By opening a dialog session record, become
available all detailed information including the Summary that show you all the
prompt and response messages with the actual values eventually retrieved from
the message configuration record discussed previously.
The dialog sessions historical logging feature
of MS Dynamics CRM is very useful not only for the developers but also for the
final users because it allow him to review a session and even to make some
analysis on the functional flow.
Hope it can be useful.
Happy CRM coding