Add-Ins in Dynamics NAV 2013 (2#3) – Add-in exposing custom API to C/AL
Introduction
Add-Ins in NAV 2009 where all about data binding a custom visual component through the Source Expression of the field to a data source – a variable on a page or a field in a table. Data for a an add-in would be transferred when the page updates and changed values from the add-in would be transferred back and saved when the page saves data. The add-in could influence a little, by triggering the OnControlAddIn Trigger or requesting saving of data through the Site.
While these concepts lead the developer to a “document oriented” thinking (documents conforming to data models and possibly configuration models), it imposed also some limitations. It was not always easy (yet possible) to build a document communication model that allowed C&AL to send small signals and requests to the add-in and request values. In any case it required always serialization of a object structure into a document and deserialization on the other side, in either direction.
In NAV 2013 we have introduced Custom Interfaces for client add-ins. These are basically select methods, properties and events that dynamically extend the C/AL programming interface of the respective field on the page. An Add-In developer simply declares any public Method or Property or Event of the Add-In class with the new Attribute [ApplicationVisible], and as soon as an Add-In get assigned to a page, the field has those Methods and Properties available, even through the Symbol Editor (F5). Events that have been equipped with the attribute above will be represented as new server side triggers in the C/AL code code written in those triggers will be called as soon as the Add-In calls the event on the client.
For the restless reader (“in a few words”)
- Add-In developer can expose “custom interfaces” to C/AL : public methods, properties and events with the [ApplicationVisible] attribute.
- Application Visible methods and properties are available for C/AL code at design and runtime, provided the Add-In library can be found.
- Application Visible events will be represented as new triggers for the respective fields on the page
- The Lync communication Add-In is a sample that shows how to use this technology
- Soon: Download of the the Lync Add-In: I am working on making it possible to share that.
A sample: Lync communication Add-In with custom interfaces
An add-in for Lync communication is sample for how custom Add-In interfaces may be used custom interfaces for different purposes:
This Lync communication Add-In shall support the following behaviors:
- Consume a SIP address under which Lync client through its Lync server will try to identify a communication contact from the own or any federated directory of communication contacts.
- Shows the presence of the communication contact - as far as available through federation
- Provides UI entry points to any available communication channel and shows general communication contact information that can be pinned to the desktop
- Allows the user to search for a communication contact
- Provides search suggestions as defined by C/AL code
- Has different appearances, like honoring the layout specifics for task pages and fact boxes
For this purpose we design the Add-In interface in the following way:
- Use data binding with the Source Expression to receive the SIP address from the underlying field
- Provide custom interfaces that allow the C/AL developer to set the display characteristics, also by a set of predefined styles (Option field like)
/// <summary> /// Adjusts the control for usage in taskpage / factboxes /// </summary> /// <param name="context">The context.</param> [ApplicationVisible] public void SetAddInControlContext(AddInControlContext context) { ... }
- Provide a method to set a list of search candidates to the Add-In. This takes actually a .NSTR string collection as a parameter which will be created in C/AL code and passed over without the need for serialization.
/// <summary> /// CAL method: sets the search candidates /// </summary> /// <param name="candidates">The search candidates</param> [ApplicationVisible] public void SetSearchCandidates(StringCollection candidates) { ... }
- Expose an event from the Add-In, where in the corresponding trigger it is save to initialize the Lync control Add-In. Please note the type of the Event: MethodInvoker. Typically event types in .NET like to use one parameter for the sender of the event. With Add-Ins this is not feasible, because it would be the client side instance of the Add-In – depending on what object the Add-In would send. When sending over this object in a client-server event, the call would internally involve serialization, which is not supported by must .NET types and must be prevented in order to be display target independent. C/AL shall have only access to the field and such the ApplicationVisible exposed elements of the interface.
/// <summary> /// Event will be fired when the Add-In is ready for communication through its API /// </summary> [ApplicationVisible] public event MethodInvoker AddInReady;
Relation of .NET interop and Custom interfaces of Add-Ins
On the first glance writing C/AL with .NET interop objects and Add-Ins appears to be rather similar. But there are important differences:
- While Add-Ins appear as if they
- One difference is that .Net interop objects are always instantiated with one of its constructors (or a factory method which call the constructor). Yet the instance of the Add-Ins (or it’s server side representation of the custom interface) is just there, as soon as the page has been fully created. Unfortunately there is not default place in code where the instance of the server side representation of the Add-In can be assumed to exit. Therefore for Add-Ins, where the server side use case typically requires a signal to now when the Add-In has been created on the client, the above suggested introduction of the AddInReady event is good solution.
Structure of the Lync AddIn
The LyncCommunicationControl is a WPF composition of multiple controls from the Lync control SDK with customized templates and interactions.
The LyncCommunicationAddIn, the the router between NAV and the WPF control.
Typical Call flow with an AddIn with custom interfaces
What’s going to happen if …
What is going to happen if the Add-In has been changed in the interface since it had been used on a page ?
It might be necessary to remove and reassign the Add-In to the field in order to have the code regenerated that interfaces with the Add-In custom interfaces. This is especially the case for C/AL Triggers that represent the custom events. Typically though a compilation error can be expected, until the interfacing C/AL code has been updated.
What happens with the C/AL Code that interfaces with custom interfaces if the Add-In is removed from a field?
If you remove an Add-In which has introduced Triggers for ApplicationVisible events, the a warning dialog will be shown in the development environment, indicating that those triggers together with the code that has been written in them will be deleted.
What happens if a display target runs a page that does not support Add-Ins at all ?
The Web Client of Dynamics NAV 2013 does not yet support Add-Ins. But what happens if a user runs still somehow opens such a page in the Web client?
A display target that does not support Add-Ins yet, (like the Web Client) will simply not at all show a field that has an Add-In assigned -as if this field was not visible. But if the C/AL code on the page calls into the custom interface of an Add-In the developers of the Add-In and the C/AL have to take special care:
E.g. by exposing an event like AddInReady from the Add-In which the Add-In will call as soon as it is ready to operate (e.g. after the control which he Add-In provides has been given a parent). In C/AL code in the corresponding AddInReady trigger would remember whether that trigger has been called, and otherwise not try to call into the Add-In custom interface. On a display target that does not support Add-Ins such trigger would never be called.
What’s next ?
In the next blog post of this series I will take a closer look at the Sizing support for Add-In fields and present an update of the Registration and troubleshooting tools for Add-Ins.
Christian Abeln
Senior Program Manager
Microsoft Dynamics NAV
Comments
- Anonymous
June 09, 2014
Hi ChristianI realise this blog was a while ago, and you haven't been blogging for a while (we miss you - come back) - but on the off chance you are still around. I am trying to create an Add-In that exposes an Event where the parameter is an object of a class I have created.Everything seems fine and C/SIDE seems to know what object will be coming back in the Event trigger, but when it runs the actual object is type System.Object so at runtime calling any of the properties throws an error.I found this quote above, which I'm not sure I understand. Are you saying my class needs to be serializable, or are you saying I can't use classes at all for event parameters (I have tested that strings etc... work fine)."When sending over this object in a client-server event, the call would internally involve serialization, which is not supported by must .NET types and must be prevented in order to be display target independent. C/AL shall have only access to the field and such the ApplicationVisible exposed elements of the interface."ThanksNikolai