How to write a .NET Control for Microsoft Navision

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 prerequisites:

  1. You have to explicitly define an interface in your .NET code and have the class implement the interface
  2. 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
  3 
  4 <Assembly: AssemblyKeyFileAttribute("sgKey.snk")> 
  5 
  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
  4 
  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
  8 
  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 Navision.

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 published.

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 the Assembly.

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 type:

tlbexp NavisionControl.dll /out:NavisionControl.tlb

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:

regasm /tlb:NavisionControl.tlb NavisionControl.dll

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 tool:

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:

IF ISCLEAR(MyCntr) THEN
 CREATE(MyCntr);

On the OnOpenForm trigger we'll place the code below:

CntString:=MyCntr.SaySomething;
MESSAGE('The .NET 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:

CLEARALL();

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 executed. Simple?

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 fantasy!

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?

Print | posted on Monday, September 19, 2005 3:04 PM