After my previous post
about how to use a .NET control with Navision,
I've received lots of email requests and comments on how to write a control with
.NET that can work and talk with Navision.
Unfortunately I've discovered that there's not specific documentation about
this on the net and so I hope that this post could be useful for everyone that
works with Navision, but remember that the procedure is just like writing a .NET
component and call it from a COM component.
.NET code is not directly accessible to COM clients
and in order to use .NET code from a COM client, you need to create a proxy
class, normally known as a COM Callable Wrapper. When you have to create a .NET
class that will be used by COM clients, you have to keep in mind 2
- You have to explicitly define an interface in your .NET code and have
the class implement the interface
- Any class that must to be visible to COM clients must be declared
public. The same rule applies to methods, properties, and events that will be
used by COM clients.
After that, we can start building our control...
Open Visual Studio .NET and create a new project (Class Library or User
Control as the Project Template).
After that, rename the Class1.vb file with
the name of your project (for example NavControl.vb), select the code window and start by
defining the interface that your component has to implement:
1 Imports System.Runtime.InteropServices
2 Imports System.Reflection
4 <Assembly: AssemblyKeyFileAttribute("sgKey.snk")>
6 Public Interface INavControl
7 Function SaySomething() As String
8 End Interface
Here we have defined an interface named INavControl where a function called SaySomething() is defined. This function will be the
method of our .NET Controls that works with Navision.
Now we have to define a public class that must implement this interface.
The class will be defined as follow:
1 <ClassInterface(ClassInterfaceType.AutoDual)> _
2 Public Class NavisionControl
3 Implements INavControl
5 Public Function SaySomething() As String Implements INavControl.SaySomething
6 Return "Hi, I'm the .NET Control and this comes from my function"
7 End Function
9 End Class
This class implements the function SaySomething
that in this example is only a simple
function that, when called, returns a string to the caller.
Now we have to register our .NET component in order to use it in
Before compilation, the assembly containing the class
that will be used by Navision must be signed with a cryptographic key pair
(strong name). Signing an assembly with a strong name helps .NET ensure
that the code in the assembly has not been changed since the assembly was
To create a strong name you can use the sn.exe tool from
the Visual Studio Command Window:
sn -k sgKey.snk
A file named sgKey.snk will be created and the line <Assembly:
AssemblyKeyFileAttribute("sgKey.snk")> in our code wil use it to sign
Now you can compile the project and a file named NavisionControl.dll will be created. In order to
register it and use the newly created component with Navision, you've to follow
these 3 steps:
First, you must create a type library for the
assembly (a type library is the COM equivalent of the metadata contained
within a .NET assembly) and in order to do this, open the Command Window and
After that, you have to use the Assembly Registration Tool (regasm.exe) to both create the type library and
register it in a single operation:
At the end, you must install the .NET assembly into the Global Assembly Cache
(GAC) so that it will be available as a shared assembly. To install an assembly
into the GAC, you've to use the gacutil.exe
gacutil /i NavisionControl.dll
Now you're ready to use your component in Navision.
To test it, open the Navision Object Designer, create a new blank form and
declare a global variable named MyCntr with
DataType = Automation. Select the SubType
by pressing the Assist Edit button and (on the list of controls that will appear
to you) select NavControl.NavisionControl. Now
your .NET control is declared in Navision.
We've also declared a string variable named CntString that will contained the
string message returned to Navision from the .NET control.
In Navision, the form's C/AL Global section will appear as follow:
Now, in order to test the control, open the code window for this form and on
the OnInit trigger of the form place the
code to instantiate the control:
On the OnOpenForm trigger we'll place the
control has returned this string: %1',CntString);
This code launch the SaySomething method of
the .NET control and place the returned string into the CntString variable. Then it shows a message to the
user with the returned string.
To complete the little project, on the OnCloseForm trigger we have to release all the
resources used by the .NET control, so place the code below:
The example is finished... if you compile and run this newly created form
this is the result:
When the form is executed, the control is instantiated and the .NET method is
This is obviously only a simple example but it shows exactly all the steps
that you have to do in order to create a .NET control that is able to work with
Navision. The SaySomething methos here is really
stupid (it returns only a string) but it could be really complex and it could
perform database operations, connect to the web etc... The limit is only your
I hope to have given a clear example on how to perform these tasks... Maybe
I've opened a new window for all Navision's developers that reads my blog?