Microsoft Dynamics NAV
Developer Updates for
Microsoft Dynamics NAV
2009 R2
User's Guide
Contents
Developer Updates for Microsoft Dynamics NAV 2009 R2 ... 1
Viewing the Definition of a Function or Object by Using Go To Definition ... 2
Locking and Unlocking Objects ... 9
How to: Lock an Object ... 10
How to: Unlock an Object ... 11
How to: Integrate Classic Client Report Designer and Visual Studio Report Designer ... 12
Extending Microsoft Dynamics NAV Using Microsoft .NET Framework Interoperability ... 14
Calling .NET Framework Members from C/AL Code ... 15
How to: Call .NET Framework Members from C/AL Code ... 18
How to: Set .NET Framework Types to Target the RoleTailored Client or Microsoft Dynamics NAV Server ... 21
.NET Framework and C/AL Type Mappings ... 23
Using .NET Framework Arrays ... 26
Using .NET Framework Collections ... 30
Using .NET Framework Enumerations ... 31
Using .NET Framework Generics ... 33
Using .NET Framework Interfaces ... 35
Calling External Web Services with Windows Communication Foundation ... 36
How to: Add a FactBox on a Page Using the Wizard ... 38
Developer Updates for Microsoft Dynamics NAV
2009 R2
This document describes the new developer tasks that you can perform in Microsoft Dynamics NAV 2009 R2.
For more information about what’s new in Microsoft Dynamics NAV 2009 R2, including what’s new in the application, see What’s New in Microsoft Dynamics NAV 2009 R2 in the MSDN Library. You can also find this content in the What’s New in Microsoft Dynamics NAV 2009 R2.pdf file, which is located in the Documentation folder. By default, this folder is C:\Program Files\Microsoft Dynamics
NAV\60\Documentation.
For more information about the hotfixes and known issues in Microsoft Dynamics NAV 2009 R2, see the Microsoft Dynamics NAV 2009 R2 Release Notes (requires PartnerSource login). You can also find the release notes in the ReadMe.htm file on the installation media.
In This Section
Viewing the Definition of a Function or Object by Using Go To Definition Locking and Unlocking Objects
How to: Integrate Classic Client Report Designer and Visual Studio Report Designer Extending Microsoft Dynamics NAV Using Microsoft .NET Framework Interoperability How to: Add a FactBox on a Page Using the Wizard
Viewing the Definition of a Function or Object by
Using Go To Definition
You can view the definition of a function or object by selecting the item in the C/AL Editor and then clicking Go To Definition. You can also view the definition of a function by selecting it in the C/AL Globals window and then clicking Go To Definition.
To go to the definition of a function or object, select or place the cursor anywhere in the function name or object variable name, and then do one of the following:
On the View menu, click Go To Definition.
Right-click the function name or object variable name, and then click Go To Definition.
Press SHIFT+F12.
The following table describes how you can go to the definition of a function or object.
Starting location Result
From the C/AL Globals window, select a user-defined function
The C/AL Editor goes to the C/AL code that defines the selected function.
From the C/AL Editor, select a user-defined function The C/AL Editor goes to the C/AL code that defines the selected function.
From the C/AL Editor, select a user-defined function that is called on an object variable
The object is opened in the corresponding designer.
A new C/AL Editor window opens to the C/AL code that defines the selected function.
From the C/AL Editor, select a system function on an object
If the system function is called on an object variable, such as a record, codeunit, or report, then the object is opened in the corresponding designer. If the system function is not called on an object variable, then nothing happens.
From the C/AL Editor, select a variable that is one of the following object types:
Record
Page
Form
Report
The object is opened in the corresponding designer or editor:
Table Designer
Page Designer
Form Designer
Examples
This section shows examples of using the Go To Definition shortcut menu item.
User-Defined Function from the C/AL Globals Window
From the C/AL Globals window, right-click a user-defined function, and then click Go To Definition.
User-Defined Function from the C/AL Editor
From the C/AL Editor, right-click a user-defined function, and then click Go To Definition.
User-Defined Function from the C/AL Editor for an Object Variable
From the C/AL Editor, right-click a user-defined function that is called on an object variable, and then click Go To Definition.
The result is that the object on which the function is called is opened in the corresponding designer and a new C/AL Editor window opens to the C/AL code that defines the selected function.
System Function from the C/AL Editor
From the C/AL Editor, right-click a system function that is called on an object variable, and then click Go To Definition.
If the system function is called on a record variable, then the table that the record is from is opened in Table Designer.
If the system function is called on any other object type variable, then the object is opened in the corresponding designer. For any other system function that is not called on an object variable, nothing happens.
Object Variable from the C/AL Editor
From the C/AL Editor, right-click a variable that is one of the following object types, and then click Go To Definition: Record Page Form Report Codeunit Dataport XMLport
The object is opened in the corresponding designer: Table Designer Page Designer Form Designer Report Designer C/AL Editor Dataport Designer XMLport Designer
Permissions
To go to a definition, you must have the correct permissions. If you do not have permission to view the definition of an object by selecting the object in Object Designer and then clicking Design, then you cannot view it with the Go To Definition option.
Locking and Unlocking Objects
In Microsoft Dynamics NAV 2009 R2, you can lock an object in Object Designer so that other developers cannot save design changes to the object. After you lock an object, the Locked field in Object Designer is selected, and the Locked By column shows the user who locked the object.
When an object is locked, another user can still do the following:
Open the object in the designer, make changes, and compile the object. However, another user cannot save the object. The locked object is marked as Read Only when another user opens it in the designer.
Run the object. For example, a user can run a table and can add or delete records in the table even if it is locked for design changes.
When you finish making design changes to an object, you can unlock it in Object Designer. The Locked and Locked By fields are cleared, and other users can now lock the object or save changes to the object. You can select one object or multiple objects at the same time to lock or unlock. You can also set the Auto-Lock on Design option to automatically lock all objects that you open for designing.
Object Table
The information in the Locked and Locked By columns is stored in the Object table. The Object table is a system table that stores information about objects in the application.
Concurrency Considerations
Even though you can lock objects, it is still possible for developers to have concurrency issues, as shown in the following examples.
A developer opens an object in the designer but does not lock it. The developer makes several changes to the object and saves the changes periodically. At the same time, a second developer locks the object, and the first developer cannot save design changes to the object. The first developer gets an error message that the object is locked by the second developer.
A developer locks an object. A second developer opens the locked object in read-only mode, and then the first developer unlocks the object. The second developer still cannot save design changes to the object even though the object is now unlocked because it is open in read-only mode.
See Also
How to: Lock an Object How to: Unlock an Object
How to: Lock an Object
You can lock objects so that other developers cannot save changes to the objects. You can either lock objects manually, or you can set an option so that all objects that you open for design are locked.
1. In the Classic client, on the Tools menu, click Object Designer.
2. In Object Designer, select one or more objects that are not already locked, and then do one of the following steps:
Right-click the object or objects, and then click Lock.
On the File menu, click Lock.
Press CTRL+ALT+L.
1. In the Classic client, on the Tools menu, click Options.
2. In the Options window, in the Auto-Lock on Design field, enter Yes, and then click OK. Tip
You cannot automatically unlock objects that you have locked. However, you can filter for locked objects, select all objects that you have locked, and then unlock these objects. For more information, see How to: Unlock an Object.
Note
If you go to the definition of an object, then the object is opened in design mode. Therefore, if you set the Auto-Lock on Design field and then go to the definition of an object, then the object is locked. For more information, see Viewing the Definition of a Function or Object by Using Go To Definition.
See Also
How to: Unlock an Object Locking and Unlocking Objects
To manually lock an object
How to: Unlock an Object
You can lock and unlock objects to prevent other developers from making changes while you work with those objects. If you lock an object, then only you can save changes to the object. After you save your changes, you unlock the object so that other developers can make changes to that object.
In some cases, a system administrator may need to force unlock an object. For example, if a user locks an object and then cannot unlock the object because of a holiday or other absence, then the system administrator can force unlock the object. To force unlock an object, the system administrator must have the SUPER user role.
In some cases, you may want to unlock all objects that you have locked. To do this, you can filter on locked objects, select all objects that you have locked, and then unlock these objects.
1. In the Classic client, on the Tools menu, click Object Designer.
2. In Object Designer, select one or more objects that you have locked, and then do one of the following steps:
Right-click the object or objects, and then click Unlock.
On the File menu, click Unlock.
Press CTRL+ALT+U.
1. In the Classic client, on the Tools menu, click Object Designer.
2. In Object Designer, select one or more objects that you want to force unlock, and then do one of the following steps:
Right-click the object or objects, and then click Force Unlock.
On the File menu, click Force Unlock. 3. Confirm that you want to force unlock the object.
Note You must have the SUPER user role to force unlock an object.
1. In the Classic client, on the Tools menu, click Object Designer. 2. In Object Designer, click All.
3. On the View menu, click Table Filter.
4. In the Table Filter window, enter Locked By in the Field field, enter your user name in the Filter field, and then click OK.
5. On the Edit menu, click Select All, and then do one of the following steps:
Right-click the object or objects, and then click Unlock.
On the File menu, click Unlock.
Press CTRL+ALT+U.
See Also
How to: Lock an Object
Locking and Unlocking Objects
To unlock an object
To force unlock an object
How to: Integrate Classic Client Report Designer and
Visual Studio Report Designer
To create and modify client report definition (RDLC) report layouts, you must use Visual Studio. When you create an RDLC layout for a report, you may have to perform some steps in Classic client Report Designer to modify the dataset and some steps in Visual Studio Report Designer to modify the layout. To work with both Classic client Report Designer and Visual Studio Report Designer, you must know when and where to save your work and how to switch between them efficiently.
You can save changes to the RDLC report layout of the report in Visual Studio multiple times and then return to Classic client Report Designer and load the changes that you made to the layout into the report. In Microsoft Dynamics NAV 2009 R2, you can save and compile changes to the report dataset in Classic client Report Designer multiple times and then return to Visual Studio Report Designer and reload the dataset into the report layout.
To switch between Classic client Report Designer and Visual Studio Report Designer, we recommend that you follow these steps:
Before you switch from Visual Studio Report Designer to Classic client Report Designer, save the report.rdlc file. You can also build the report in Visual Studio before you switch to the Classic client, but this is not required.
Before you switch from Classic client Report Designer to Visual Studio Report Designer, save and compile the report.
After you update the dataset in Classic client Report Designer, you must refresh the dataset result in Visual Studio Report Designer. In the Website Data Sources pane, expand DataSet, right-click Result, and then click Refresh.
If you rename a field in Classic client Report Designer, then you must update all instances of that field in the Visual Studio Report Designer layout. Otherwise, the report will not successfully compile.
If you delete a field in Classic client Report Designer, then you must delete all instances of that field in the Visual Studio Report Designer layout. Otherwise, the report will not successfully compile.
The following procedure describes how to switch between Classic client Report Designer and Visual Studio Report Designer.
1. In the Classic client, on the Tools menu, click Object Designer.
2. To either create or modify an RDLC report, do one of the following steps:
5. Click Yes to load the changes that you made to the RDLC layout into the Classic client. 6. In the Classic client, on the File menu, click Save.
7. In the Save dialog box, select Compiled, and then click OK. Note
If you try to close the report in Object Designer in the Classic client, then you see the following error: You must close the Visual Studio Designer window before closing the report object.
Note
If you try to view the layout when the report layout is already open, then you see the following error: The report layout is already open in Visual Studio.
8. In Classic client Report Designer, make some additional changes to the report dataset. 9. In the Classic client, on the File menu, click Save.
10. In the Save dialog box, select Compiled, and then click OK. Important
If you save the report but do not compile it or if you compile the report but do not save it, then you cannot load the changes into the RDLC report layout in the following step. You must both save and compile the report.
11. Go to Visual Studio Report Designer. You see the following message: This file has been modified outside of the source editor. Do you want to reload it? Click Yes or Yes to All to reload the changes from Classic client Report Designer into the RDLC report layout.
12. In Visual Studio, in the Website Data Sources pane, expand DataSet, right-click Result, and then click Refresh. The additional items that you added to the dataset in Section Designer in the Classic client are displayed in the Visual Studio dataset.
13. You can continue making changes in either Visual Studio Report Designer or Classic client Report Designer without having to close either designer. You must save and compile the report object after you make changes and load the changes into the report object or the RDLC report layout when you are prompted.
Extending Microsoft Dynamics NAV Using Microsoft
.NET Framework Interoperability
You can extend the RoleTailored client and Microsoft Dynamics NAV Server with functionality that is available in Microsoft .NET Framework assemblies. You can take advantage of .NET Framework interoperability so that Microsoft Dynamics NAV objects can interact with .NET Framework objects. In your Microsoft Dynamics NAV objects, you can reference .NET Framework assemblies and call their members directly from C/AL code. You can use assemblies from the .NET Framework class library, which are found in the global assembly cache; your own custom assemblies; or third-party assemblies. For more information, see Assembly Installation in the GAC in the MSDN Library.
.NET Framework interoperability offers an alternative to COM so that you can extend your solution. For example, you can use .NET Framework interoperability to:
Consume web services.
Integrate with Microsoft Office products.
Create .NET Framework applications that can target the RoleTailored client.
See Also
Calling .NET Framework Members from C/AL Code .NET Framework Type Conversion
Using .NET Framework Arrays Using .NET Framework Collections Using .NET Framework Enumerations Using .NET Framework Generics Using .NET Framework Interfaces
Calling .NET Framework Members from C/AL Code
You can call .NET Framework type members, including methods, properties, and constructors, from C/AL code with the DotNet data type for C/AL variables. This section provides an overview of the DotNet data type, guidelines on its use, and aspects about calling members of a .NET Framework type. For
information about how to create and use a DotNet variable to call members of a type, see How to: Call .NET Framework Members From C/AL Code.
DotNet Data Type
The DotNet type resembles the Automation type in C/AL except that it references a .NET Framework type in an assembly. Assemblies can be either part of assemblies that are installed in the global assembly cache or custom assemblies that you have installed for Microsoft Dynamics NAV. After you have defined a DotNet variable, you can call it in C/AL code to instantiate members of a .NET Framework type.
Constructors
A constructor is a method that creates an instance of an object and prepares it for use. Before you use a DotNet variable, you should verify whether the variable is static or is an object instance because this determines whether you have to use a constructor.
Static variables do not require a constructor because they do not have an instance.
Object instance variables require a constructor because they must be created before they can be accessed.
To find the constructor and other methods and property for your object, in Object Designer, click Symbol.
Static and Instance Method Calls
Methods that you call from C/AL code can be either static or instance methods.
You use the same syntax to call static and instance methods.
Calling static methods provides a factory pattern for creating object instances. For example, to create a new System.TimeZoneInfo object, you call the type’s System.TimeZoneInfo.Local static method with the following code:
zone := zone.Local;
A static class or object is loaded once per Microsoft Dynamics NAV Server instance, and the class or object is shared between all clients that are connected to the server instance. The data that is maintained by the static class or object is visible by all clients that use the type. You should consider this in your .NET Framework interoperability design to help avoid disclosing private information.
C# Indexers
A C# indexer is represented as an Item property in C/AL. For example, in C#, the following code sets an array element N to the value M:
arrayVariable[N] = M;
In C/AL, the corresponding code is as follows:
arrayVariable.Item(N) := M;
Indexers can also be overloaded. In Object Designer, click C/AL Symbol Menu to see the parameters and return types for the indexer.
Indexers for lists and arrays that are defined by .NET Framework variables are zero-based, which means that they start at 0. Other indexers in C/AL start at 1.
Operators for Comparing .NET Framework Objects
.NET Framework interoperability does not support direct use of operators to compare two DotNet variables. For example, the following scenario is not supported:
IF dnVersion1 <= dnVersion2 THEN
If you want to compare two DotNet variables, then you can use the Equals function on the DotNet variables as shown in the following example:
IF dnVersion1.Equals(dnVersion2) THEN …
You can perform comparisons by using .NET Framework methods and properties that return compatible C/AL types because these objects are implicitly converted to C/AL types before the comparison takes place. For example, the following C/AL code includes three DotNet variables for the
System.Collections.Generic.List class: dotNetList1, dotNetList2, and dotNetList3. You cannot compare the DotNet variables directly because they do not return C/AL types. You can perform comparisons on the List.Capacity property because the List.Capacity property is a NET Framework integer type that returns a C/AL integer type. For more information about conversion between .NET Framework and C/AL types, see .NET Framework Type Conversion.
dotNetList1 := dotNetList1.List(5); dotNetList2 := dotNetList2.List(10); dotNetList3 := dotNetList3.List(5);
IF dotNetList1.Capacity <> dotNetList3.Capacity THEN ERROR('List1 and List3 should have the same capacity.');
IF dotNetList1.Capacity = dotNetList2.Capacity THEN
ERROR('List1 and List2 should not have the same capacity.');
Case Sensitivity in Member Names
.NET Framework member names in C/AL code are case-sensitive. If you use the incorrect case when you call a member, then you get an error when you compile the object. This behavior differs from other C/AL variables because you can mix cases and still compile the object. For other C/AL variables, the case is corrected automatically the next time that you open the object.
Local DotNet Variable Limitations
You should not assign a local DotNet variable to global C/AL or .NET Framework objects because the local DotNet variable is disposed when it goes out of scope. If you use the DotNet variable outside the scope of its local function, then you should define it as a global DotNet variable.
How to: Call .NET Framework Members from C/AL Code
You can call .NET Framework type members, including methods, properties, and constructors, from C/AL code. To call members, you define a DotNet type variable that references the .NET Framework assembly type that contains the member and then call the variable from C/AL code of the Microsoft Dynamics NAV object. A .NET Framework interoperability example is included in this topic.
1. If the assembly that you want to reference is a custom assembly and not installed in the global assembly cache, then copy the assembly to the Add-ins folder of the Microsoft Dynamics NAV installation folder.
By default, the path to the installation folder is C:\Program Files\Microsoft Dynamics NAV\60\Classic.
For more information, see Global Assembly Cache in the MSDN Library. Tip
You can install the assembly in the global assembly cache with the GAC utility. For more information, see GAC Utility in the MSDN Library.
2. In the Classic client, open Object Designer, and then open the object that will use .NET Framework interoperability, such as the page or codeunit.
3. To open the C/AL code for the object, on the View menu, click C/AL Code.
4. To create the variable for .NET Framework interoperability, do one of the following steps:
To create a global variable, on the View menu, click C/AL Globals.
To create a local variable, on the View menu, click C/AL Locals.
Important
A local DotNet variable, including any resources that it references, is disposed after the C/AL function to which it belongs is run.
5. On the Variables tab, in the Name field, type a name for the variable. 6. Set the DataType field to DotNet.
7. In the SubType field, click the AssistEdit button to open the .NET Type List window. 8. In the Assembly field, click the AssistEdit button to open the Assembly List window. 9. If the assembly that you want to reference is in the global assembly cache, then click the .NET
1. Open the C/AL code for the object.
2. On the View menu, click C/AL Symbol Menu.
You can use the C/AL Symbol Menu window to help you call constructors, members, and properties of the .NET Framework type.
3. In your C/AL code, add the following code to call the constructor that creates a new instance of the type. If you are calling a static method, then a constructor is not required, and you can skip this step.
MyVariableName.ConstructorName(arguments);
The MyVariableName variable is the name of the .NET Framework variable.
The ConstructorName variable is the same as the type name.
The arguments variable represents any parameters that you must set for the constructor.
Note
Member names are case-sensitive. Also, constructor names that are longer than 30 characters are truncated after 30 characters.
4. Add the following code to call the methods or properties.
MyVariableName.MethodPropertyName(arguments);
The MethodPropertyName variable is the name of the method or property that you want to call, and the arguments variable represents any arguments of the method or property.
Important
Some types in the System namespace of the .NET Framework class library are automatically converted to C/AL types. You cannot assign values to .NET Framework variables for these types. For more information, see .NET Framework Type Conversion. Note
Methods can be overloaded. Therefore see the description at the bottom of the C/AL Symbol Menu, which shows the parameter and return types for each method. Also, method and property names that are longer than 30 characters will be truncated, and you cannot compile the Microsoft Dynamics NAV object. For more information, see Calling .NET Framework Members From C/AL Code
Example
Description
The following code example uses .NET Framework interoperability to display headlines from an RSS feed from the Microsoft Dynamics NAV team blog, which has the following URL:
http://feeds.feedburner.com/MicrosoftDynamicsNavTeamBlog?format=xml.
This example calls members of the System.XML assembly, which is part of the Microsoft .NET Framework class library and is installed in the global assembly cache.
To implement this example, you create a codeunit that has the following local variables.
Variable name DataType SubType
xml DotNet 'System.Xml, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.System.Xml.XmlDocument items DotNet 'System.Xml, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.System.Xml.XmlNodeList
i Integer
title DotNet 'System.Xml, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.System.Xml.XmlNode
After you create the codeunit, add the following code to its OnRun trigger. Code xml := xml.XmlDocument(); xml.Load('http://feeds.feedburner.com/MicrosoftDynamicsNavTeamBlog?format=xml'); items := xml.SelectNodes('/rss/channel/item'); FOR i := 0 TO items.Count - 1 DO BEGIN title := items.Item(i).SelectSingleNode('title/text()'); MESSAGE( title.Value ); END Comments
To see the example in the RoleTailored client, you can create an action on a page that opens the codeunit.
See Also
How to: Set .NET Framework Types to Target the RoleTailored Client
or Microsoft Dynamics NAV Server
To extend a Microsoft Dynamics NAV object with .NET Framework interoperability, you define a C/AL variable that calls members of a .NET Framework type in an assembly. When the variable is called from the C/AL code of the Microsoft Dynamics NAV object, it creates an instance of the .NET Framework type. You can set the type instance to target the RoleTailored client or Microsoft Dynamics NAV Server. By default, an assembly is set to target Microsoft Dynamics NAV Server. However, you can set the type to target the RoleTailored client.
You cannot set different types of the same variable to target both the RoleTailored client and Microsoft Dynamics NAV Server.
Setting the .NET Framework Type to Target the RoleTailored Client
To set a .NET Framework type instance to target the RoleTailored client, you must complete the following tasks as described in this topic:
Set the DotNet variable for the .NET Framework type to target the RoleTailored client.
Copy the .NET Framework assembly to the computer running the RoleTailored client.
You must copy the assembly to each computer running the RoleTailored client. If the assembly is included in the global assembly cache, then you do not have to do this task.
1. In Object Designer, open the Microsoft Dynamics NAV object that uses .NET Framework interoperability.
2. Do one of the following steps:
For a global variable, on the View menu, click C/AL Globals.
For a local variable, in the C/AL Editor, select the trigger that uses the DotNet variable, and then on the View menu, click C/AL Locals.
3. On the Variables tab, select the DotNet variable, and then on the View menu, click Properties. 4. In the Properties window, set the RunOnClient property to Yes.
On the computer running the RoleTailored client, copy the.NET Framework assembly to the Add-ins folder of the RoleTailored client installation.
By default, the path of this folder is C:\Program Files\Microsoft Dynamics NAV\60\RoleTailored Client\Add-ins.
Note
You can also put assemblies in a subfolder of the Add-ins folder. This can be useful when you have multiple versions of the same assemblies and dependencies. Important
Note
To set the .NET Framework type to target the RoleTailored client
Setting the .NET Framework Type to Target Microsoft Dynamics NAV Server
To set a .NET Framework type instance to target Microsoft Dynamics NAV Server, you must complete the following tasks as described in this topic:
Set the variable for the NET Framework type to target Microsoft Dynamics NAV Server.
Copy the .NET Framework assembly to the computer running Microsoft Dynamics NAV Server.
If the assembly is included in the global assembly cache of the computer running Microsoft Dynamics NAV Server, then you do not have to do this task.
1. In Object Designer, open the Microsoft Dynamics NAV object that uses .NET Framework interoperability.
2. Do one of the following steps:
For a global variable, on the View menu, click C/AL Globals.
For a local variable, in the C/AL Editor, select the trigger that uses the DotNet variable, and then on the View menu, click C/AL Locals.
3. On the Variables tab, select the NET Framework variable type, and then on the View menu, click Properties.
4. In the Properties window, set the RunOnClient property to No.
On the computer running Microsoft Dynamics NAV Server, copy the .NET Framework assembly to the Add-ins folder in the Microsoft Dynamics NAV Server installation folder.
By default, the path of the Microsoft Dynamics NAV Server installation folder is C:\Program Files\Microsoft Dynamics NAV\60\Server\Add-ins.
Note
You can also put assemblies in a subfolder of the Add-ins folder. This can be useful when you have multiple assemblies and dependencies.
See Also
Note
To set the .NET Framework type to target Microsoft Dynamics NAV Server
.NET Framework Type Conversion
In C/AL, some .NET Framework data types, such as strings, integers, and decimals, are automatically converted to C/AL types. Because the types are converted, the .NET Framework versions of these types are not supported in C/AL. For example, instead of using a .NET Framework integer data type in your C/AL code, you should use a C/AL integer data type. When the C/AL integer is sent back to a .NET Framework object, such as through a method call, then the C/AL integer is automatically converted to a .NET Framework integer.
Conversion Table for .NET Framework and C/AL Types
The following table lists the automatic data type conversions between.NET Framework and C/AL types. .NET Framework type
(range) C/AL type (range) Comments System.Byte (0..255) Char (0..255)
Single unsigned byte that represents a value from 0..255.
System.SByte
(-128..127)
Integer (-128..127)
Single signed byte that represents a value from -128..127.
System.Char
(0..65535)
Integer
(±2,147,483,647)
Unicode character that is represented internally as a 16-bit unsigned integer.
System.Int16 (-32768..32767) Integer (±2,147,483,647) System.Int32 (-2,147,483,648..2,147,483,647) Integer (±2,147,483,647) System.Int64 (-9,223,372,036,854,775,808.. 9,223,372,036,854,775,807) BigInteger (±9,223,372,036,854,775,807) System.UInt16 (0..65335) Integer (±2,147,483,647)
Microsoft Dynamics NAV does not have a corresponding type, but values can be stored in an integer.
System.UInt32
(0..4,250,000,000)
BigInteger
(±9,223,372,036,854,775,807)
Microsoft Dynamics NAV does not have a corresponding type, but values can be stored in a BigInteger. System.UInt64 (0..18,446,744,073,709,551,615) Decimal ( 0.. 18,446,744,073,709,551,615)
Microsoft Dynamics NAV does not have a corresponding type, but values can be stored in a decimal. System.Single (±3.402823e38) Decimal (±3.402823e38) System.Double (±1.79769313486232e308) Decimal (±1.79769313486232e308)
.NET Framework type (range) C/AL type (range) Comments System.Decimal (±79,228,162,514,264,337,593,543, 950,335) Decimal (-999,999,999,999,999.99.. 999,999,999,999,999.99)
An internal range that is not persisted to a field but is the type’s native value range.
System.Int32
(±2,147,483,647)
Option
(±2,147,483,647)
Option values can be freely converted to numeric values. The range is the same as an integer.
System.Enum
(-32768..32767)
Integer
(±2,147,483,647)
An enumeration is a named constant whose underlying type is any integer type except Char. If no underlying type is explicitly declared, then Int32 is used. Microsoft Dynamics NAV has no knowledge about the constant’s name but only knows the value.
System.Bool (TRUE, FALSE) Boolean (TRUE, FALSE) System.String (0 to 1024 bytes) Text (0 to 1024 bytes) BigText (up to 2 gigabytes)
Denotes a text string with a maximum length of 1024 characters. Text strings are single-byte only.
System.String
(0 to 1024 bytes)
Code
(0 to 1024 bytes.)
Denotes an alphanumeric string with maximum length of 1024 characters. The value is stored in uppercase.
System.DateTime
3 January year 1 .. 31 December 9999
Date
1 January year 1753 .. 31 December 9999
The common language runtime only supports DateTime. In Microsoft Dynamics NAV, Date must be converted to a DateTime value type when passing as a parameter, such as for CREATEDATETIME(d, 000000T);.
.NET Framework type (range) C/AL type (range) Comments TimeSpan (Resolution is 100 nanoseconds) Duration (Resolution is 1 millisecond)
A time interval is the duration of time or elapsed time that is measured as a positive or negative number of days, hours, minutes, seconds, and fractions of a second. Duration is internally represented as a 64-bit integer.
System.Guid
(128-bit number)
GUID
(128-bit number)
System.IO.Stream InStream Streams require a context specific
conversion and specialized stream types such as {Stream,String,Text}{Reader,Writer} classes. BLOB-related streams should typically use MemoryStreams.
System.IO.Stream OutStream
See Also
Using .NET Framework Arrays
An array is a data structure that contains several variables of the same type. The variables are treated as a single collection. Although you can already create arrays in C/AL, you can now use arrays from the .NET Framework. Choosing whether to use a C/AL array or a .NET Framework array depends on how you intend to use the data.
For this scenario Use this array type
Your C/AL code uses .NET Framework interoperability extensively, and you must share an array among many methods.
.NET Framework array Your C/AL code mostly uses basic C/AL types and does not interoperate with
the .NET Framework.
C/AL array
To use a .NET Framework array in C/AL, you must use the System.Array class in the .NET Framework class library, which is the class from which all arrays inherit. When interfacing with an array in C/AL, you must use the following methods of the System.Array class to create and access elements in the array.
Method Description
CreateInstance Creates a new array instance that is passed to a method or property. SetValue Sets a value in an array element.
GetValue Gets a value from an array element
Many .NET Framework classes implement these methods. Therefore, they are available for you to use in C/AL code. If you are writing your own .NET Framework code and want to use it in Microsoft Dynamics NAV, then you must implement these methods yourself.
In C/AL, some .NET Framework data types, such as strings, integers, and decimals, are automatically converted to C/AL types. If a .NET Framework array contains these data types, then you create an assembly that contains methods that return the information about the data types and then reference the assembly in the C/AL code. This concept is illustrated in the following examples.
Example: Using Native C/AL Data Types in a .NET Framework Array
The following example shows how you can use a .NET Framework array for an integer data type.
1. In Visual Studio, create a C# class library project called NavInteropHelper that contains a method that returns the information about the integer type as follows:
2. Build the project, and then copy the assembly to the Add-ins folder of the Microsoft Dynamics NAV installation folder. By default, the path of the installation folder is C:\Program Files\Microsoft Dynamics NAV\60\Classic.
3. In the Classic client, open a Microsoft Dynamics NAV object, open the C/AL code, and then create the following C/AL variables.
Variable name
DataType SubType
varDotNet DotNet 'NavInteropHelper, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null'.Microsoft.Dynamics.Nav.NavInteropHelper.WrapInt32 varArray DotNet 'mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.System.Array arraySize Integer
i Integer alData Integer
4. On a trigger of the Microsoft Dynamics NAV object, add the following C/AL code to create, fill, and implement the array.
// Sets the number of elements in the .NET Framework array. arraySize := 10;
// Creates an instance of the .NET Framework array that contains the Int32 type. varArray := varArray.CreateInstance(varDotNet.GetTypeOfInt32(), arraySize);
// Clears the object instance because it is no longer used. clear(varDotNet);
// Sets the data in the array. FOR i := 0 TO (arraySize -1) DO varArray.SetValue(i+100,i);
// Gets the array data and validates the content. The object that is returned by // GetValue is automatically converted into a C/AL integer in the assignment.
FOR i := 0 TO (arraySize -1) DO BEGIN
alData := varArray.GetValue(i); if alData <> (i+100) then
error('Invalid array data in element %1, expected %2, actual %3', i, i+100, alData);
END;
Example: Using User-Defined Classes in a .NET Framework Array
This example shows how you can use a .NET Framework array that includes user-defined classes. 1. In Visual Studio, create a C# class library project called NavInteropHelper that contains methods that
return the information about the types as follows.
namespace Microsoft.Dynamics.Nav.NavInteropHelper; {
public class WrapInt32 {
public int Data { get; set; } public WrapInt32(Int32 value) {
Data = value; }
} }
2. Build the project, and then copy the assembly to the Add-ins folder of the Microsoft Dynamics NAV installation folder. By default, the path of the installation folder is C:\Program Files\Microsoft Dynamics NAV\60\Classic.
// Sets the number of elements in the .NET Framework array. arraySize := 10;
// Creates an instance of the .NET Framework object so the type information // can be retrieved.
varDotNet := varDotNet.WrapInt32(1);
// Creates an instance of the .NET Framework array that contains the // user-defined type.
varArray := varArray.CreateInstance(varDotNet.GetType(), arraySize);
// Clears the object instance because it is no longer used. clear(varDotNet);
// Sets data in the array. FOR i := 0 TO (arraySize -1) DO BEGIN
varDotNet := varDotNet.WrapInt32(i+100); varArray.SetValue(varDotNet,i);
END;
// Gets array data and validates content. FOR i := 0 TO (arraySize -1) DO
BEGIN
varDotNet := varArray.GetValue(i);
// Gets the integer value from the .NET Framework object using the Data property. alData := varDotNEt.Data;
if alData <> (i+100) then
error('Invalid array data in element %1, expected %2, actual %3', i, i+100, alData);
END;
See Also
Calling .NET Framework Members from C/AL Code How to: Call .NET Framework Members From C/AL Code .NET Framework Type Conversion
Using .NET Framework Collections
In Microsoft Dynamics NAV, a common development task is to write code that loops through a set of records and performs an operation on each record in the set. You can do the same task in the .NET Framework with a collection, which is a .NET Framework object that you can iterate over. To loop through a collection in Microsoft Dynamics NAV, the .NET Framework object must support the System.Collections interface. Many types in the .NET Framework and assemblies that inherit from .NET Framework types support the System.Collections interface. The following example shows how you can write C/AL code to handle collections for a type that supports the System.Collections interface.
Example
The following example implements the System.Collections.ArrayList interface and uses the
GetProcesses method from the System.Diagnostics.Process type to display a list of process IDs in message boxes. Although this is not a typical example for an ERP product such as Microsoft Dynamics NAV, it shows the flexibility that you get with the .NET Framework.
The example requires that you define the following C/AL variables.
Variable name DataType SubType
MyProcessList DotNet 'mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.System.Array Process DotNet 'System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.System.Diagnostics.Process
I Integer
MyProcessList := Process.GetProcesses(); FOR I:=0 TO (MyProcessList.Length()-1) DO BEGIN
Process := MyProcessList.GetValue(I); MESSAGE(FORMAT(Process.Id));
END;
Using .NET Framework Enumerations
In the .NET Framework, an enumeration commonly represents constant values as symbolic or literal names. For example, if you have the type Color, then instead of using the values 0, 1, and 2, you can use
Red, Green, and Blue. In C/AL, you must assign an enumeration to an Integer data type, so you must convert symbolic names in the .NET Framework to integers in C/AL.
Example
This example shows how to use an enumeration in integer expressions in C/AL and then convert the text string back to an integer to store it in the enumeration variable. In the following C# example, the
enumeration is contained in the Microsoft.Dynamics.Nav.EnumSample assembly.
namespace Microsoft.Dynamics.Nav.EnumSample; {
public class DataTypes public enum ItemEnum { Item1, Item2, Item3, Item4 }; } }
In the Microsoft Dynamics NAV object, define the following C/AL variables.
Variable name DataType SubType Length
varDotNet DotNet 'Microsoft.Dynamics.Nav.EnumSample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=18cff5e0dac2f853'. Microsoft.Dynamics.Nav.EnumSample.DataTypes.ItemEnum
formatResult Text 30
alInteger Integer
To handle the enumerator type, add the following code to a C/AL function.
// Assign an integer to the .NET Framework enumeration. // This assigns Item3 because enum values are zero-based. varDotNet := 2;
// Convert the enum object to a text string, which is equivalent to the // .NET Framework ToString method.
formatResult := format(varDotNet); if formatResult <> 'Item3' then
error('Wrong enumeration value. Expected %1, but actual was %2.', 'Item3', formatResult);
// Assuming that the enum value is stored as a text string, convert it back to the // proper enum value.
varDotNet := varDotNet.Parse(varDotNet.GetType(), 'Item4');
// The varDotNet enum should now contain the integer value 3 and the enum 'Item4'. alInteger := varDotNet;
if alInteger <> 3 then
error('Wrong enumeration integer value. Expected %1, but actual was %2.', 3, alInteger);
formatResult := format(varDotNet); if formatResult <> 'Item4' then
error('Wrong enumeration value. Expected %1, actual was %2.', 'Item4', formatResult);
See Also
Calling .NET Framework Members from C/AL Code How to: Call .NET Framework Members From C/AL Code .NET Framework Type Conversion
Using .NET Framework Generics
In the .NET Framework, you can use generics to customize a method, class, structure, or interface according to the data type that it acts upon. Instead of writing a method, class, structure, or interface for a particular type, you can write it to use any type. When a generic is instantiated, the type is specified. For example, if you use the generic type parameter T, then you can write a List<T> class that is instantiated as either List<int>, List<string>, or List<MyClass>.
With .NET Framework interoperability, you can define DotNet variables for generics. You cannot specify generic type names in C/AL. When a generic is instantiated by a constructor in C/AL, all type names are set to the System.Object type. For example, if you have a mylist DotNet variable for the System.List<T>
generic, you create an instance of mylist in C/AL as shown. mylist is instantiated as a List<Object> type.
mylist := mylist.List();
If a method returns an instance of a generic whose type name is defined, then the type name is applied. In the following example, the method returns a List<String> instance, and mylist is instantiated as a
List<String> type.
mylist := x.GetAStringList();
Example
The following example constructs a string list, fills the list with data, and then uses the Item method to validate whether the list contains the expected data. The Item method is equivalent to a C# index operator.
Variable name
Data Type SubType Length
varDotNet DotNet 'mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.System.Collections.Generic. List`1 textResult Text 30 i Integer capacity Integer capacity := 5; varDotNet := varDotNet.List(capacity);
FOR i:= 0 TO (capacity-1) DO varDotNet.Add(FORMAT(i));
IF varDotNet.Count <> capacity THEN
ERROR('Wrong list count, expected {0}, actual {1}', capacity, varDotNet.Count);
FOR i:= 0 TO (capacity-1) DO BEGIN
textResult := varDotNet.Item(i); IF textResult <> FORMAT(i) THEN
ERROR('List index [%1] contains the wrong data, expected %2, actual %3', i, FORMAT(i), textResult);
END;
See Also
Calling .NET Framework Members from C/AL Code How to: Call .NET Framework Members From C/AL Code
Using .NET Framework Interfaces
With .NET Framework interoperability in C/AL, you can define variables for .NET Framework interface types. This is useful when you have a class that explicitly implements an interface. In the .NET Framework, when an interface is explicitly implemented, you cannot call methods that belong to the interface directly from the class instance. To call a method, you must cast to the interface. This condition is similar in C/AL except that C/AL does not have a cast operation. In C/AL, you cannot call a method of an explicitly implemented interface directly on the DotNet variable for the class. Instead, you do the following steps:
1. Create a DotNet variable for the interface. 2. Assign the class variable to the interface.
3. Call the interface methods on the DotNet variable for the interface.
Example
In the following C# example, you have the Sample class that explicitly implements the ISample interface.
class Sample : ISample { ... string ISample.Name() { ... } }
To call the ISample.Name method from C/AL code, you create the following variables.
Variable name DataType SubType (simplified)
cvar DotNet Sample
ivar DotNet ISample
After you create the variables, add the following code that assigns the class variable to the interface variable and then calls the interface’s method.
// Assigns the class variable to the interface variable. ivar := cvar;
...
// Calls the method of the interface. ivar.Name();
Calling External Web Services with Windows Communication
Foundation
In Microsoft Dynamics NAV 2009 R2, you can use the Windows Communication Foundation, which provides a set of reliable objects for calling web services to use with .NET Framework interoperability.
Example
The following code example uses a proxy web service class and calls a Read method from the Microsoft Dynamics NAV web service. To set up this example, you expose page 42 as a web service in the Web Service table and then generate and compile the proxy class. For more information, see Working with Web Services in the MSDN Library.
The example requires the following variables.
Variable name DataType SubType Length
navBinding DotNet 'System.ServiceModel, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.System.ServiceModel.BasicHttpB inding
address text 256
salesOrderService DotNet 'SalesOrderService, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null'.NAV.SalesOrderService.SalesOrder_PortClient endpointAddress DotNet 'System.ServiceModel, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089'.System.ServiceModel.EndpointA ddress
salesOrder DotNet 'SalesOrderService, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.NAV.SalesOrderService.SalesOrder
navBinding := navBinding.BasicHttpBinding;
// Set security mode to BasicHttpSecurityMode.TransportCredentialOnly navBinding.Security.Mode := 4;
address :=
// Include the sales order ID to be read. salesOrder := salesOrderService.Read('10000');
See Also
Calling .NET Framework Members from C/AL Code How to: Call .NET Framework Members From C/AL Code
How to: Add a FactBox on a Page Using the Wizard
In Microsoft Dynamics NAV 2009 R2, you can use the Page Wizard to add a FactBox to a new page. A FactBox is an area that is located on the right side of a page, and you can use FactBoxes to display other pages, charts, or system parts.
List
ListPlus
Navigate
Worksheet
If you want to add a FactBox without using the wizard, see Walkthrough: Adding a FactBox to the Customer List Page in the MSDN Library.
1. In the Classic client, on the Tools menu, click Object Designer. 2. In Object Designer, click Page, and then click New.
3. In the New Page dialog box, click Create page using wizard, and then select one of the following page types from the list:
Card Document List ListPlus Navigate Worksheet
4. To associate a table with the page, in the Table text box, click the AssistButton, select a table, and then click OK.
5. Click OK to go to the next step in the wizard.
6. Continue the wizard until you get to the step that asks you about which FactBoxes to include on the page.
7. Depending on what part you want to add, click either the Page, System, or Chart tab. 8. Select the part from the list, and then click the > arrow to add it to the Part Order list on the
right.
9. Repeat steps 7 and 8 to add more parts.
The part’s vertical position in the Part Order list determines its vertical position in the FactBox on the page.
10. To remove a part, click the Page, System, or Chart tab based on the part type, select the part from the Part Order list, and then click the < arrow.
11. Finish the steps in the wizard.
For more information about the wizard and creating pages, see How to: Create a Page in the MSDN Library.
Note
How to: Use the System Indicator
You can enable the system indicator when you are working with different instances of Microsoft Dynamics NAV 2009 R2. For example, you can differentiate between a production environment and a test
environment or see when you are in configuration mode. In this procedure, you enable and set up the system indicator.
If you are in configuration mode, then the system indicator is automatically displayed, and you cannot turn it off.
If you are in any other mode, then you must first set up the system indicator in the Company Information window. It is then shown according to your preferences on every page.
1. In the RoleTailored client, in the navigation pane, click Departments, click Administration, click General, and then click Company Information.
2. Expand the System Indicator FastTab.
3. In the System Indicator field, select one of the following options.
System indicator type Description
None No text is shown.
Note
When you are in configuration mode, the
Configuration status is always displayed. You cannot turn this text off.
Custom Text Shows text that you enter in the System Indicator Text field.
Company Information Shows text that you enter in the Name field.
Company Shows the company name.
Database Shows the middle-tier host name and database name.
Company+Database Shows the company name, the middle-tier host name, and the database name.
Microsoft Dynamics is a line of integrated, adaptable business management solutions that enables you and your people to make business decisions with greater confidence. Microsoft Dynamics works like and with familiar Microsoft software, automating and streamlining financial, customer relationship, and supply chain processes in a way that helps you drive business success.
U.S. and Canada Toll Free (888) 477-7989 Worldwide (1) (701) 281-6500
www.microsoft.com/dynamics
The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, this document should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication.
Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.
Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.