Unified Service Desk Best Practices (Part 2) – Using FireRequestAction
Background on FireRequestAction
Creating custom USD hosted controls is an extremely powerful extension mechanisms. In fact, USD itself is built on such hosted controls. I recall a quote of which I paraphrase, "With great power comes great responsibility." This quote definitely holds true with USD hosted controls as well. USD hosted controls are built on an extensible code based framework called User Interface Integration (UII).
While it is generally discouraged in USD, UII had a commonly used concept for calling actions configured on other hosted controls. The function to do this is, "FireRequestAction".
Why you shouldn't call FireRequestAction
FireRequestAction essentially calls a function defined in another control without having a reference to the control itself. By using the name of the target control and the name of an action to call, as long as the action is defined in the configuration and exists in the code of the target control, that controls code will be executed. The big downside here is that this function directly calls the action and bypasses the Unified Service Desk action call pipeline. The result is that such actions still have a dependency on the admin defining the action for the target hosted control, but the admin will not see the request for that action in the USD Debugger. If the admin goes and deactivates the target action, the application stops working but the admin cannot tell why it has stopped working because they will see nothing in the debugger.
Instead of calling FireRequestAction, it is generally suggested that control writers not create such a tight dependency on another control, particularly it's name. Instead, we suggest that you fire an event using FireEvent. FireEvent will show up to the admin in the debugger, even if they have not defined the event in the admin. This is helpful because it is an indication to the admin that it is available to them to hook, if they desire. Also, the admin can decide the appropriate action to take based upon business need, rather than the control developer assuming they know what the admin will want to do in response to their event. As a result, the admin will add an Action Call to the Event definition in CRM, which will in turn call the target controls action. If the name of the target control changes, the admin automatically updates the chain so everything still works. If the action call is deactivated, the admin will see the event is fired and nothing happens, as he intended. The other benefit to FireEvent is that the source and target controls are decoupled such that the code of both know nothing of the other. Both can be changed, modified, replaced, without an impact on the other. The admin can also decide to do something completely different with the event than what was imagined at the time the control was created, which is a very powerful concept.
When you should call FireRequestAction
There is only one scenario when it is recommended that you call FireRequestAction. This one scenario is when creating a CTI Hosted Control. While there are alternatives to calling FireRequestAction in USD CTI Adapters to trigger a screen pop, the CTI Framework that is part of UII provides this as the mechanism to use. In particular, if you wish to create a CTI adapter that will work in both USD and UII applications, you will want to follow the CTI Framework guidance and use FireRequestAction. Here is a typical CTI event trigger from within a CTI adapter.
Dispatcher.Invoke(() =>
{
CtiLookupRequest data = new CtiLookupRequest(Guid.NewGuid(), base.ApplicationName, qParams["calltype"], qParams["ani"], qParams["dnis"]);
data.Items.AddRange(itemsList);
base.FireRequestAction(new RequestActionEventArgs("*", CtiLookupRequest.CTILOOKUPACTIONNAME, GeneralFunctions.Serialize<CtiLookupRequest>(data)));
}
);
What if I do call FireRequestAction?
If you do call FireRequestAction, whether in UII or USD, you should always remember that it is little different from calling a function directly in another module within a .NET application. The most important take away from this, is that many target actions do UI manipulation and will not check to make sure that the calling thread is the UI thread. They will typically assume that the caller knows to always call FireRequestAction on the UI thread, as would happen with the configuration methods. This is also true with CTI adapters. CTI adapters have a tendency to look for events from a CTI server on a non-UI thread, which is good, but if you intend to call FireRequestAction to initiate a screen pop from one of these events, it is important that you first call Dispatch.BeginInvoke to release the current thread to continue processing but also to get the call onto the main UI thread in preparation for calling FireRequestAction.
Best Practice
- Except for a CTI Hosted Control, never call FireRequestAction.
- If you do call FireRequestAction, always ensure the call is made from the UI thread.
Thank You!
Please leave your feedback and suggestions for future blogs in the comments section.
You can find more Best practices for Unified Service Desk here
Jayme Pechan contributed to this blog post
Comments
- Anonymous
June 14, 2016
FireRequest action can return a value though, so the calling method knows if the request was successful. With your design pattern based on events, how would the calling method know if the request was successful or not?- Anonymous
June 15, 2016
The comment has been removed - Anonymous
June 17, 2016
Another pattern that exists inside USD can be found in the screen pop flow. The CRM Global Manager calls FireEvent. If there are any Action Calls defined, then processing following FireEvent simply exits. The admin can take the screen pop data, modify it if needed and either do his own screen pop or may call the ScreenPop action on Global Manager with the modified data to pick up where it left off but with modified data. In a way, this can be thought of as returning a value. It is also used on the SessionClosing event and a few other places.
- Anonymous