Bootcamp Notes: DotNet, Streams & .NET

The title looks like talking about .NET twice, but actually, the first is using DotNet variables in code, the second is using .NET as an add-in.

Personally, I found this subject the most interesting, just because of all the great things you can achieve by using DotNet variables in C/AL.

Maybe some of you already used DotNet variables in NAV2009R2, but in NAV2013 using DotNet becomes even more fun. No more thinking about where your code is used. Before DotNet only ran on RTC, but since even NAS is now running through NST you can just use DotNet everywhere.

A bit of knowledge of .NET gets you a long way. So it might not be a bad idea to put a little time into it. Think about Overloading, reflection, static vs dynamic classes, Serialisation, …

Let’s start with Text variables. Text variables are actually DotNet String variables now, which means you can assign them directly between each other and start using all possible methods available on the .NET String Class.
Vjeko also talked about appending text on text variables. We used to do += or something like that. But doing this actually uses a lot of memory. The same applies when using a BigText and the ADDTEXT method. A better way is to create a DotNet variable of type StringBuilder. It is designed to handle appending text better. To demonstrate, Vjeko assigned a complete Customer Table multiple times to a text variable, a BigText variable and a StringBuilder. When showing the run times, you can really spot the speed difference. In long assignments, you will notice StringBuilder only using a fraction of the time that Text, String or BigText need. He basically compared assigning by using += with a guy that is painting. He puts his bucket of paint at the start and goes back to his bucket every time he needs his paint. The StringBuilder works like taking his bucket with him.

Most of the default NAV types are directly possible to TypeCast against a .NET Class. NAV Objects such as records are “secured” by Microsoft, so these can not even be TypeCasted against an object. Still you can use the function GETDOTNETTYPE to check the type in .NET. It uses the TypeOf .NET function.

Another handy function is the CANLOADTYPE. With this function you can check if the class library is installed where you try to load it. If the Assembly is not available, you can take action instead of letting it fail…

DotNet uses references, which means when creating a 2 DotNet variables and assign them to each other, both will have the same object in memory. Same as passing data to a function ByRef. This also makes the ByVar property in a parameter of NAV useless, because DotNet is always “ByVar”
Since it works with references, you cannot compare DotNet vars with each other directly. Doing something like “IF DotNet1 = DotNet2 THEN” does not work. It is even disabled to do on DotNet vars. Each DotNet variable has a function “Equals” to compare the data in it. To check if the reference the same object in memory, you also have the ReferenceEquals method on a DotNet var.

DotNet vars are also case sensitive, simply because .NET also is. A method “function” is not the same as calling the method “FuncTion”.
Because of DotNet interoperability and event handling, function names can now be longer, up to 128 characters.

NAV does not support asynchronous events. Trying to fire events asynchronously will actually crash your session…

When creating a DotNet variable, you may also have noticed that it is not very clear how to find a specific class. A good method is starting with the base assembly, then move to system, then mscorlib. Let’s give an example, you look for System.IO.Stream, First start with System.IO, then go to System, next look in mscorlib.
Another possibility is lookup the Class on MSDN. Here you will see the information next to assembly takes you to the correct assembly without looking in NAV.

When you have a local DotNet variable, you can assign it to a global variable. You will set the reference to the memory location, except this is not a good way to work. In the background of .NET there is something called the garbage collector which runs periodically. It cleans up memory of no longer used objects. This could mean that your global variable will no longer be instantiated if it ran in-between. If you really need this in some cases, NAV create a property on a local DotNet variable which is called “SuppressDispose”, which makes sure that garbage collector does not kill it.

DotNet variables have a property “RunOnClient” to execute them on NST or on the client level. If you run them on the client, they need to be installed on the client (or at least put in every RTC Add-In folder). Every time you run a variable on the client, it asks permission to the user once per session per class. If you only run a class on the server, there is no need to install it on the client. Except on the client where the developer works, otherwise (s)he will be unable to compile.

Now let’s talk .NET… I’ll try to make everything as clear as possible, but please don’t shoot me if I repeat stuff, or am not able to clear it up completely. There is just sooooo much to talk about in .NET. By the way, both framework 4 and 4.5 are supported.

Dynamics vs Static classes. If you create a class, you can declare it static. If you compare to NAV, it is a bit like a SingleInstance CodeUnit. Except, the static class is loaded in NST. You could actually share data between sessions then. It is not shared between NST instances.

When assigning a client variable to a server side variable, there are no references to exchange. Then the data is copied to the other variable. In .NET this process is known as serializing. Remember this will only work if the class you use is serializable. Which means with own classes, you need to explicitly set this.

By using the global assembly cache or putting subfolders in the Add-In folder you can maintain different version of a class at once.

Next to making your own classes, you can create Client Control Add-Ins. By using control add-ins you can make RTC look differently than what it is capable of, like textbox background color, Masked Textboxes, …
Multiple events are supported for the Add-in now as well and you can call methods on the control (CurrPage.FieldName.YourAddin).

You could use control add-ins to bypass the security confirmation of DotNet variables to a user. A control add-in is supposed to be trusted and does not ask permission.

A control add-in cannot be added on a repeater field.


Why talking about streams separately? Because blobs in NAV no longer support the EXPORT and IMPORT, and you will need streams.

Just like text variables, streams are directly exchangeable with .NET streams. You can use a .NET variable of type stream as a variable of an XMLPort. However, for some reason, you cannot use a function CREATE(IN)(OUT)STREAM with a DotNet variable, here you still need InStream and OutStream NAV variables…

The NAV CopyStream function does the same as .CopyTo()

Another thing you could achieve with streams is Unicode captions. I mentioned this before in another post. Since Development Client does not support Unicode, we cannot create Unicode captions. But since everything is stored in the Object Metadata table, we could theoretically stream the captions into the XML.

It has been a long read, if you managed to get here. And this will be the end of my post. I think I mentioned the most important and interesting things. If you do have questions or things are unclear, please let me know.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.