• Microsoft Dynamics NAV Team Blog

    Using Client Extensibility in NAV 2009 SP1 to create Charts



    Just to get a bit of practice with Client Extensibility, I experimented with some examples I got. They use MS chart controls to build chart

    components for RTC. As it turned out, the result was something that might even be useful as well. So this post has these two

    purposes: 1)  Some relatively simple examples of Client Extensibility, and 2)  hopefully in the process to make something that can

    actually be useful.


    Of course - as always - the information in this post is un-supported and no responsibility is assumed. In particular when working with

    Client Extensibility add-ons, one has to be careful of handling any potential error in the add-on. If the add-on meets an unhandled exception,

    then RTC may crash. So if you decide to extend the example here (and I hope you do), then just be careful to trap as many potential

    exceptions as possible in your Visual Studio code. This is lesson one for creating Client Extensibility Add-ins...


    However I would encourage any feedback - just post it here at the end of this post. Is this useful, what else would be useful, etc. Both

    for learning this new technology, and I would also welcome any ideas for charts that might be useful.


    Also check these links for much more information on Client Extensibility:
      Christian's blog
      Extending the RoleTailored Client Using Control Add-ins in Microsoft Dynamics 2009 SP1


    New blogs on this topics may follow - all depending on the response to this one. For now, this post shows how to achieve two different types of charts, looking like this:





    Making charts with Clients Extensibility for NAV 2009 SP1 using the "Microsoft Chart Controls add-on for MS Visual Studio"

    First, you need to download and install these two components:

    Microsoft Chart Controls Add-on for Microsoft Visual Studio 2008

    Microsoft Chart Controls for Microsoft .NET Framework 3.5


    Then from here you can take the easy way and just use the completed project that I attached at the end of this post. Or the hard way, and follow the full directions below. First, if you just want to see what this is, here is how to implement this example from the files attached here:


    Implement the Client Add-in control:

    As the name suggests, Client Extensibility add-ons run on the client (RTC). In NAV 2009 SP 1, the RTC folder contains a new subfolder called "Add-ins" (default C:\Program Files\Microsoft Dynamics NAV\60\RoleTailored Client\Add-ins). So unzip the attached file "XTCharts.zip", then copy the files from "XTCharts\bin\Debug\" into the Add-ins subfolder in RTC.

    Next, open a Classic Client and "Register" this add-in for the client: Run table 2000000069 "Client Add-in", and enter a new line:

    Control Add-in Name:    XTChart
    Public Key Token:    d1a25808afd603da

    It's important that you call it exactly this, since both the Add-in Name and the Public Key Token refer to these specific dlls (explained further below).

    This example includes codeunit 75550 "XT Chart Util" which has functionality generating the data that the charts are based on. So import XTChart.fob.

    Finally, add a chart control to a page. For this example add it to page 21 "Customer Card": In Page Designer, first create a new global variable called XTChartUtil, Type = Codeunit, SubType = XT Chart Util. To add the line-chart:

    add a new line called "Sales (LCY)" of type "Field", and specify these two properties:

    SourceExpr = XTChartUtil.CustPointsChart(Rec)

    ControlAddIn = XTChart;PublicKeyToken=d1a25808afd603da

    And to add the pie-chart, add a new line with these proerties:

    SourceExpr = XTChartUtil.CustDoughnutChart(Rec)

    ControlAddIn = XTChart;PublicKeyToken=d1a25808afd603da

    Save and compile the page, then start RTC, and the Customer Card page should now look as in the picture above.


    What this example gives, is: 1) A chart showing "Sales (LCY)" for the last 6 months, and a doughnut chart that shows the percentage of Balance compared to Credit Limit.

    Designing the client Add-in control:

    Hopefully by following the steps above, you should now have charts on your Customer Card. So here is how you would have designed it from scratch instead of using the attached example.

    To get started, open up Visual Studio 2008. Create a new project of type Class Library. In the project that opens, in the Solution Explorer, right click References, and select "Add Reference...". Here we need to add a few references:

    From the "Browse" tab, browse to the folder where you have Dynamics NAV RoleTailored Client installed (default C:\Program Files\Microsoft Dynamics NAV\60\RoleTailored Client), and select Microsoft.Dynamics.Framework.UI.Extensibility.dll. This is the library that is always needed when making a Client Extensibility add-on.

    Add another reference, this time from the ".NET" tab select System.Windows.Forms.DataVisualization. This is the library that you installed from the links above. And, finally, also from the ".NET" tab, add System.Windows.Forms

    Also add references to these in code, like this in the top:

    using System.Windows.Forms.DataVisualization.Charting;

    using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;

    using Microsoft.Dynamics.Framework.UI.Extensibility;

    using System.Windows.Forms;


    And now you are ready to start using functionality from Client Extensibility, and from Microsoft Chart Controls.

    To start any Client Add-in control, you need two things:

    [ControlAddInExport()]-declaration just before the class you make, and

    protected override Control CreateControl() which is the function that RTC runs when initialising a Client Extensibility Add-in. Your project should now look like this:



    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Windows.Forms.DataVisualization.Charting;

    using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;

    using Microsoft.Dynamics.Framework.UI.Extensibility;

    using System.Windows.Forms;

    namespace ClassLibrary8



    public class XTChartClass : StringControlAddInBase


    protected override Control CreateControl()


    Chart XChart = new Chart();

    return (XChart);





    You must remember the name you decide on, in this line:


    This is the name (XTChart) that must match the entry in table 2000000069 "Client Add-in".

    This is the minimum code needed - you can of course now also specify a number of properties for your chart control, like colours, chart types, etc. As long as you create your control here, and then return it back to RTC.

    The next question is: how do we send data from RTC to our control? This done by adding these lines:

    public override string Value




    return base.Value;




    base.Value = value;




    This is the Value that you get from RTC. RTC sends it via the SourceExpression of the Control Add-in when you add it to a page. When you add an Add-in to a page you don't have to specify SourceExpression, but if you want to send data from RTC to the Add-in, then this is how to do it. In this example there is a codeunit to generate chart-data, but SourceExpression can also just be a field.

    In the section you just created, you can now refer to the chart like this: 


    So when receiving data from RTC, you can then set ChartType, Data, and any other properties on the chart.


    You must also sign the project: In Project Properties, on the "Signing"-tab, you must tick "Sign the assembly". This embeds a public key token in the .dll when you build it, and this is the token (here d1a25808afd603da) that must also be entered into table 2000000069. Visual Studio does not tell you what the token is, so to obtain it, after building your project open a Visual Studio Command Prompt, and run "sn -T XTCharts.dll" to find out what the public key token is for XTCharts.dll.


    In this example, we send an XML structure to the Add-in, which is generated by the codeunit. The structure is like this:

    - <Chart>
    - <Data>
     So basically, we have one node for the Chart Type (1 is for a point-chart, and 2 is for a doughnu chart). And then there is a data-section for the Series in the chart.
    Finally, in the code below, also notice these lines:

    try { - do code..}

    catch{MessageBox.Show("An error occurred ");}

    I am not a c# developer, so this way of doing error handling is likely not optimal. But if any kind of error happens in the code, and it is not inside of a try{}-structure, then the Add-in may crash, and when that happens, RTC will also crash. In this example, instead of a crash, we would get a message and RTc would stay open.
    So, below is the whole code from the attached example. Remember this particular code is designed specifically receive data in a specific format, done by the attached codeunit. So it can of course be simplified, or of course even more so, it is something that can be improved on.
    Again, I hope this is useful for getting insight into Client Extensibility, but also maybe it can be used as a basis for making some useful components - comments are more than welcome,
    Best regards
    Full code:

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Windows.Forms.DataVisualization.Charting;

    using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;

    using Microsoft.Dynamics.Framework.UI.Extensibility;

    using System.Windows.Forms;

    using System.Drawing;

    using System.Xml;

    namespace XTCharts



    public class XTChartClass : StringControlAddInBase


    protected override Control CreateControl()


    Chart XChart = new Chart();



    XChart.Width = 100;

    XChart.Height = 100;

    return (XChart);


    public override string Value




    return base.Value;






    if (Convert.ToString(value) != "")



    String TempXML = value;

    XmlDocument XMLDoc = new XmlDocument();


    // Chart Type

    XmlNode Node = XMLDoc.SelectSingleNode("Chart/ChartType");

    switch (Convert.ToString(Node.InnerText))


    case "1":

    ((Chart)this.Control).Series["Series1"].ChartType = SeriesChartType.Spline;

    ((Chart)this.Control).BackColor = Color.AliceBlue;


    case "2":

    ((Chart)this.Control).Series["Series1"].ChartType = SeriesChartType.Doughnut;



    MessageBox.Show("Invalid ChartType " + Convert.ToString(Node.InnerText));



    // Chart Data

    XmlNodeList Nodes = XMLDoc.SelectNodes("Chart/Data/*");

    for (int i = 0; i < Nodes.Count ; i++) {

    Node = Nodes.Item(i);

    ((Chart)this.Control).Series["Series1"].Points.AddXY(Node.Name, Convert.ToDouble( Node.InnerText));




    catch{MessageBox.Show("Error with data from NAV " + value);}







  • Microsoft Dynamics NAV Team Blog

    Updated April 2nd 2009 - How to add a Company Picture to a Report


    UPDATED April 2nd 2009: Several people have reported to me that the first solution I posted for “How to use the Picture stored in Company Information table:” did not work for them. So I have now updated the section on how to use the picture stored in the Company Information table. The picture is now added in a slightly different way.



    There are several ways to do this. Either you use the existing Picture which is stored in table 79 Company Information or you can embed the image into the Report itself, or you can link to the picture externally. In this scenario I will be looking at how to use the picture already in the database and and how to embed the picture into the report itself.

    How to embed the Picture:

    1. For us to be able to embed the picture into a report we need to have the Company Picture as a file. I have exported the company picture to c:\temp\CompanyPicture.bmp

    2. Ok, now let us add this to Report 111. Design Report 111

    3. Select "View/Layout" to go into Visual Studio.


    4. Select the Report and choose "Report/Embedded Images"


    5. Select "New Image..." and select your company picture, in my case c:\temp\CompanyPicture.bmp


    6. With that completed open the Toolbox and add a Image control to the Report.


    7. With the Image Control added we need to the set correct properties for this control. Set Source=Embedded, Value=companypicutre and MIMEType=image/bmp


    9. Save and import RDLC changes, and then compile report in Classic client.

    10. Run "dynamicsnav:////runreport?report=111" to open up report 111. And as you can see below company picture is displayed.


    We have no looked at how to embed the Company Picture into the report. Now let us have a look on how to use the Company Picture already in the database.

    How to use the Picture stored in Company Information table:

    1. Deleted the above embedded Company Picture, if you followed the steps above.

    2. Design report 111

    3. Now we need to have a Variable with is references to the Company Information Table. Lets create a new called CompanyInfo


    4. Exit C/AL Globals and ad the following code to the "OnPreReport()" trigger: CompanyInfo.CALCFIELDS(Picture);


    5. Now we should add a Picture Box on the Sections with SourceExpr: CompanyInfo.Picture. We need to do this to have the element available for us in Visual Studio.


    6. It is now time to open Visual Studio. Select "View/Layout"

    7. Notice that we now have an new entry in  the DataSet


    8. Now lets add this to the report. We need to add the Company Picture first as a TextBox to the body of the report. This will enable us to use it in the Page Header. We add this TextBox in top of the Body.


    9. We give the TextBox the following properties:

    Value: “=Convert.ToBase64String(Fields!CompanyInfo_Picture.Value)”
    Name: “CompanyPicture
    Visibility Hidden: “True
    Color: “Red

    10. Now add the following code to the Report properties.

    Shared PictureData as Object

    Public Function GetPicture() as Object
    Return PictureData
    End Function

    Public Function SetPicture(NewData as Object)
    if NewData>""
    PictureData = NewData
    end if
    End Function


    11. Now let us add the Image control just as we did for the embedded scenario. Open the Toolbox and add a Image control to the Report.


    12. With the Image Control added we need to the set correct properties for this control.

    Value: “=Convert.FromBase64String(Code.GetPicture())
    Source: “Database
    MIMEType: “image/bmp

    13. Add textbox to Page Header. Note! This textbox has to be placed above the Picture control just added

    Value: “=Code.SetPicture(ReportItems!CompanyPicture.Value)
    Visibility Hidden: “True
    Color: “Red


    14. Save and import RDLC changes, and then compile report in Classic client.

    15. Run "dynamicsnav:////runreport?report=111" to open up report 111. And as you can see below company picture is displayed.



    Claus Lundstrøm, Program Manager, Microsoft Dynamics NAV

  • Microsoft Dynamics NAV Team Blog

    “User ID and password are invalid.try again?”


    If you get "User ID and password are invalid.try again?" when starting RTC you need to first check that you can login to database in the classic client. Note that the database should be the same as the service tier (the service you are trying to connect with RTC) is connected to.

    1. Start "classic client with SQL"
    2. Click File->Database->Open
    3. Pick the server the database exist one
    4. Select authentication "Windows Authentication"
    5. Pick the database
    6. Press OK

    If it works in the classic client make database login synchronization.

    1. Start "classic client with SQL" and connect to the database as above
    2. Click Tools->Security->Synchronize all logins
    3. Answer yes to the question if you would like to synchronize

    If it doesn't to connect to the database start SQL server manager and verify that the windows user have permission to login and use the NAV database.

  • Microsoft Dynamics NAV Team Blog

    Some tips about creating "Tree view" in List pages


    In Microsoft Dynamics NAV 2009 in new Role Tailored Client we have new feature – we can show lists in “tree view”. We can expand/collapse nodes and make lists more interesting and more visual.

    However this new feature isn’t documented very well and every developer needs to collect his own experience. With this article I will try to make this way easierJ

    So if we want to see Tree View we need to have:

    1.       Table with field type Integer. This field will get us major point – will show is record root or fork or leaf.

    a.       Few words about “IndentationColumnName” field; (that how property to indentation field is named on Pages)

                                                                  i.      Field could be only type Integer.

                                                                ii.      Allowed values are >=0. I didn’t find upper limit, but because view indentation shift is calculated based on this value then with “big” values filed is indented too far to right that becomes invisible.

                                                              iii.      Root record has “0” indentation. Higher numbers means higher indentation. There could be several “0” records placed on table.

    2.       Page type List.

    a.       On page designer there must be “Group” & subtype “Repeater” and we need to set on it:

                                                                  i.      Property “ShowAsTree” = Yes

                                                                ii.      Property “IndentationColumnName” must be field name we defined in table as indentation field.

    b.      Repeater must include fields we want to see in list. First field in list will be indented and will have ‘+-‘ signs for collapse/expand list. Indentation field could be not included to page.

    If everything is done (and you have data in the table), then run page. Fortunately for me I have table with some data in it:

    Few interesting points I want to have your attention:

    • Field “Int” is used for primary key
    • Field “Indentation” has indentation value used for Tree View.
    • Both fields are not used on page so field “Txt” has text showing which record and what indentation level is.
    • There are no relations between primary key and indentation. You see 0 indentation is record 18.

    So run page and see:

    If we “Expand All” we’ll see:

    Wow it works J

    Please keep in mind:

    • There could be few records with the same indentation.
    • If after record ‘A’ is going record ‘B’ with bigger indentation then we can expand record ‘A’.
    • View belongs to sorting. I sorted records based on “Indentation” value. So I see “full tree” started from “0 level”. But really “0 level” record is 18 record by primary key, and if change sorting to primary key I will see different tree.

    You see now: first record has primary key 0 and indentation level 5, but next record has level 1 so my first record has no possibilities “collapse/expand”. Record 18 with level 0 is in the end of list and only one record is after it, so “my root records from previous view” now can expand/collapse only one record.


    And last:

    • You can’t insert manually new records to “Tree View”. Please use code if you want to create new records from “Tree view”
    • You can delete records manually from “Tree view” one by one. If you will try to delete not expanded record then only this record will be deleted.
    • You can edit records in “Tree view”. You can modify even “Indentation level” field, just after modify “Refresh” (F5) and you will see “new view”.
    • There were few stability issues in “Tree view ”, so please use possible latest NAV builds
    • If you have questions/issues regarding this functionality, please contact our best ever NAV support team J


    Gedas Busniauskas
    Microsoft Lithuania
    Microsoft Customer Service and Support (CSS) EMEA

  • Microsoft Dynamics NAV Team Blog

    NAV 2009 Tips and Tricks: Create Notifications from Task Pages


    You can create notifications from task pages such as customer cards or sales orders. You can use notifications as reminders, or as a way to send information to other NAV users in your company.

    A notification is displayed on the recipient's Role Center. By clicking the notification, the recipeint opens the associated task page.

    1. To create a notification, open the task page from which you want to send a notification. For example, open a customer card, sales order, or other task page.

    2. In the FactBox area, scroll down to the Notes part.

    3. In the Notes part, click to create a new note.

    4. In the Enter a new note here text box, type a note.

    5. Select a recipient.

    6. Select Notify.

    7. Click Save.

    The notification is saved on the task page.


    The notification is also relayed to the recipient and is displayed on his/her Role Center under My Notifications.

    For more information about usability and the RoleTailored client, see the blog post Useful, Usable, and Desirable.

  • Microsoft Dynamics NAV Team Blog

    Microsoft Dynamics NAV 2009 SP1 installation moment...


    Recently i met customer problem where NAV 2009 SP1 components didn't work after "correct installation".

    Problem is: customer installs NAV 2009 SP1 components by run msi file - for example "Microsoft Dynamics NAV SDK.msi". But this way doesn't install "Prerequisite Components" needed by NAV 2009 SP1. And it could be these installed NAV components will not work (because it missing prerequisites).

    Only supported way to Install NAV 2009 SP1 components is - run "setup.exe".

    However "setup.exe" will uninstall previous NAV version and installs new NAV 2009 SP1 version. If you need to have few NAV version installed - you need to run msi (instead of setup.exe).
    So conclusion: both ways have it strength and weakness. You can choose what you want, just you need to know about possible issues...

    Gedas Busniauskas (gediminb)
    Microsoft Customer Service and Support (CSS) EMEA

  • Microsoft Dynamics NAV Team Blog

    Automation Objects in Microsoft Dynamics NAV 2009



    The Automation object is often used to integrate NAV business logic with external processes and thereby extend the functionality of the product, such as integration with other products like Office. Automation objects must expose a COM interface, and every time we cross a process boundary is worth thinking about performance, but issues that involve correct operation could have a negative impact on performance. This is something we are willing to accept. One example is that objects designed for a single thread execution must execute on Single Threaded Apartment (STA) threads. Having a look at this KB article (http://support.microsoft.com/kb/257757/) explains why office products never should be allowed to run on the server:

    Reentrancy and scalability: Server-side components need to be highly reentrant, multi-threaded COM components that have minimum overhead and high throughput for multiple clients. Office applications are in almost all respects the exact opposite. Office applications are non-reentrant, STA-based Automation servers that are designed to provide diverse but resource-intensive functionality for a single client. The applications offer little scalability as a server-side solution. Additionally, the applications have fixed limits to important elements, such as memory. These cannot be changed through configuration. More importantly, the applications use global resources such as memory mapped files, global add-ins or templates, and shared Automation servers. This can limit the number of instances that can run concurrently and can lead to race conditions if the applications are configured in a multi-client environment. Developers who plan to run more than one instance of any Office application at the same time need to consider "pooling" or serializing access to the Office application to avoid potential deadlocks or data corruption.”



    Flavors of COM

    Apartment threading

    There are two major flavors of Automation objects, ones that are designed for single threaded applications, and ones that execute well in a multithreaded environment. This doesn’t prevent one from running STA objects on the server and MTA objects on the client, but each scenario where “best practices” are deviated should be considered closely.

    An example would be the XML Document object


    The DOMDocument is a single threaded apartment version and the FreeThreadedDOMDocument is the version that utilizes a multithreaded environment, like the server. But in cases where we a free threaded version of the object is not available, it would properly be acceptable to use the version available, because the .Net runtime is managing MTA-to-STA marshaling behind the scene. This could result in bad performance and other problems – but in most scenarios it is likely to work. A closer look at “PRB: MSXML Performance Bottleneck in ShareMutex Under Stress” explains why issues like these must be considered.

    “Using the MSXML parser in a high-stress environment … may cause unusually long run times on XML requests, and the application or service can appear to stop responding (hang).“

    And the solution in this scenario would be to use the FreeThreadedDOMDocument object on the server.

    Native and Managed Automation Objects

    The Automation implementation in the Role Tailored Client and the Dynamics NAV Server utilizes the CLR implementation, and the CLR does an excellent job of allowing managed code to call out to unmanaged Automation objects. It generates a runtime-callable wrapper (RCW) proxy that implements all of the interfaces of the underlying object. Furthermore, the CLR has a built-in mapping/marshaling layer that knows how to translate the types between the native and managed domains.

    The following table shows the specific type mappings between AL, COM and their corresponding .NET types.


    All the Automation objects are late bound activated; this means that they must implement the IDispatch interface, in order for the Reflection API to be able to invoke members. Managed Automation objects are recognized by the RCW as being managed and standard CLR reflection invocation takes place. Therefore, in-process (dll) and Out-of-process (exe) Automation behaves identically if the objects are created in a managed language.


    The default account for running the NAV Server, configured at installation time, is the built-in Network Service account. This account does not have permissions to spawn a new process, as configured in Component Services, and it is not recommended to change that behavior. This is by design, in order to prevent out-of-process Automation servers (Executables with a COM Interface) to execute on the server. But if the scenario requires this, it would be a recommended practice to create a new service account with the minimum privileges plus the “Launch and Activate Permissions” of the required Automation Servers. These processes will then be created on the server and properly stays alive until they receive a specific terminate command, or the server is rebooted. Another risk with Automation servers on the NAV Server machine is that users could potentially share the same Automation process. In AL, the construct CREATE (automationServer, TRUE), will search the system for created instances of type “automationServer” and try to reuse that process, and potentially read data created by another user.

    Therefore the recommended syntax would be CREATE(automationServer, FALSE, FALSE), for Automation servers running on the NAV Server. On the client tier, no sharing can occur and it would be perfectly fine to try and reuse the Automation server.

    The in-process Automation objects whether they are created on the client or server tier are hosted by the running process and inherit the security context of the active user. The same goes for OCX controls that require an UI and therefore only will be allowed on the client side.

    Wrap-up (recommendations)

    Server tier
      • Native Automation objects: In-process automation servers, like MSXML6.dll.
      • Objects with a user interface such as OCX types.
      • Managed wrapped COM Objects
      • Objects designed for multi threaded execution (MTA)
    Client tier
    • Native Automation objects: Out of process automation servers, like Microsoft Office.
    • Objects with a user interface such as OCX types.
    • Objects designed for single threaded execution (STA)
    • It is good practice to design your Automation interfaces to get as much work done in a single method invocation. And when consuming a component, try to use it in way that minimizes chattiness. This is utmost importance for the client side automation scenario.


    COM is an immutable, interface-based model. Interface design is very important and should always be split from the implementation. Try to avoid auto-generated interfaces based on classes as they have a tendency to violate this guideline and not version well. There is a good source of information at: “Do not use AutoDual ClassInterfaceType“


    (see the first comment on this post for the text of this sample)

    - Stefan Omdahl

  • Microsoft Dynamics NAV Team Blog

    Manage Max No. of XML Records to Send Option from RoleTailored Client (with .NET Interop)


    With NAV 2009 R2 it is now possible to set how many XML records to send to RoleTailored Client (RTC), bypassing the previous hardcoded limitation of 5000 records.

    This could be done by installing platform hotfix KB 2492490 Build no. 32146 or higher.



    I just would like to explain how this Hotfix works in short.

    In order to bypass the previous hardcoded limit of 5000 Max no. of xml records to send, after installing the aforementioned platform hotfix or higher, you have to set a key like that on every RTC Client machine in the ClientUsersSettings.config file

    <add key="MaxNoOfXMLRecordsToSend" value="integerValue" />

    (where integerValue is an integer value that represents the max number of xml records to send when using the Export to Microsoft Office feature)

    Since the Classic Client handles this value directly from the IDE changing “Max. no. of XML records to send” property from Tools > Options, I have been requested if there is a more flexible way to manage this key in the ClientUsersSettings.config file.

    I have then tried, in this blog, to mimic what Classic Client does and developed a simple page and codeunit to let the user change dynamically the value for this key and if the key is not present, by adding it directly to the ClientUsersSettings.config file with the desired value (this would also make the Hotfix deployment faster).

    The code in the attached .txt file is quite simple and is based on .NET interoperability using the following:








    These postings are provided "AS IS" with no warranties and confer no rights. You assume all risk for your use.

    Duilio Tacconi (dtacconi)

    Microsoft Dynamics Italy

    Microsoft Customer Service and Support (CSS) EMEA

    A special thanks to Jorge Alberto Torres - DK-MBS NAV Development

  • Microsoft Dynamics NAV Team Blog

    Embedding fonts into PDF


    Update: I stand corrected, embedding fonts into a PDF is not an option with the SAVEASPDF function in NAV 2009.

    But now you at least know that this is solved in our next version.



    I just want to share a small tip today. If you need to include a custom font into a RDLC report you need to first install the font, of course.

    The Font must be a True Type font. If your font is an Open Type font you will need to convert this first for it to visible in Visual Studio.

    Then you will need to restart the computer for the font to be embedded into the report when saving as PDF.

    The restart issue took me some time to figure out, so with this small tip, you hopefully will not loose as much hair as I did, when you include a custom font into a RDLC report.

    I have attached a sample RDLC report with a custom barcode font.


  • Microsoft Dynamics NAV Team Blog

    Silent or unattended installation


    What is silent or unattended installation
    Simply said silent install is installation without any UI. In this case it’s about how to run “setup.exe” in silent mode. It’s recommended that you only run “setup.exe” when you install a new NAV installation, because the installer have been tested by them using this procedure only. So by that said it’s no longer supported to install from the different msi files directly. This is true for all NAV 2009 releases. The major problem you may run into if you are installing directly from the msi files is that you will not get prerequisites (as .Net, Report Viewer and so on) installed and you will also miss out one some pre installs checks (validating that you have everything needed as outlook).

    How to-do it?
    It’s very simple. “setup.exe” does support some different parameters for this purpose:
    /quiet <– will turn of the UI
    /log [filename] <– create a log text file in the specified location
    /config [filename]<– point to the configuration file to use during the installation
    /uninstall <– will simple un install the product
    /repair <– repairs a bad installation

    The first thing that needs to be done is to create the configuration file that we will use.

    1. Star “setup.exe”
    2. Click “next”
    3. Click “I accept”
    4. Click “Choose an installation option”
    5. Click “Custom Components”
    6. Select the product that you want to install
    7. Update destination folder if needed by clicking on the “destination folder” link
    8. Click “next”
    9. Click on the component that you have picked to setup the different parameters as “server name” and so on. When done apply your changes.
    10. Click “save configuration”
    11. Pick a good location, name and save the xml file

    You can create as many configuration files as you want for different purposes. Now, you can run the silent install by simply doing start -> run -> [setupExepath] /quiet /config [configfilepath.xml]. Be sure to take a look to the log file, to ensure everything went OK.

    Example D:\setup.exe /quiet /config C:\configfiles\config1.xml /log C:\log.txt

  • Microsoft Dynamics NAV Team Blog

    Microsoft Dynamics NAV 2009 R2 Ships!


    This seems to be a good time of year for me to blog. When I do, I get to announce a new release of Dynamics NAV, and what could be more fun for someone in R & D? So I'm here again to tell you we shipped another version, this time Microsoft Dynamics NAV 2009 R2!

    Last year, I had these philosophical thoughts to open the dialog:

    "Microsoft Dynamics NAV 2009 was a release of courage. We made big bets. We wanted nothing short of transformation. And we accomplished our goal, shipping what is arguably the most significant release in Microsoft Dynamics NAV history.

    Microsoft Dynamics NAV 2009 SP1, by contrast, is a release of precision. We listened and collaborated with you, our partners and customers. We refined. We executed predictably. And, less than 12 months after the release of Microsoft Dynamics NAV 2009, we are giving you a service pack that extends the value of Microsoft Dynamics NAV 2009 and meets our joint goal of making Microsoft Dynamics NAV simply the most productive middle-market ERP product on the planet. In this way, it is just as big as the release it is built upon."

    If Microsoft Dynamics NAV 2009 was a release of courage and NAV 2009 SP1 was a release of precision, NAV 2009 R2 is a release of agility. Because of architectural investments we made in NAV 2009 and based on your increasing interest in hosting and the cloud, we were able to pull features together early and ship them to you now. Getting you value earlier and more often is something we will continue in the future, based on a more frequent release cadence. (The fact that we've shipped three versions of NAV in the past three years is indicative.)

    Since RTM blogs should have an element of the retrospective (in addition to evangelism), let's rewind a bit to spring of this year. At that time, several things happened. First, we had done some investigations about running the RoleTailored client over wide-area networks, which would dramatically improve the usability of a hosted solution while reducing its cost. Second, we realized that many of the features we'd already done in NAV "7" could be shipped early. Finally, by working with the CRM Integration team in Microsoft, we both agreed that we wanted to get the CRM-to-NAV Connector out early. Thus, R2 was born. It was announced soon thereafter at Directions EMEA in May. Quickly, we got the release feature set together, spun off the appropriate people, and moved forward. Several clever Program Managers managed to get in additional features, such as Win 7 light-up integration, online payments, filtering ability on subpages, and .NET Interop.  (This very cool last feature is also predicated on the architectural changes from NAV 2009...)

    But we had a problem.

    We were due to ship NAV 2009 SP1 in several countries in Central and Eastern Europe by the end of the year. We didn't know how we could handle another version of NAV and ship NAV 2009 SP1 to those countries that still hadn't received it. In retrospect, the answer was obvious, despite it being a course through uncharted waters: let's ship it in all the countries at the same time. So, for the first time, we give you a release of NAV in 42 countries simultaneously!

    As much as I'd like to tell you about all the great value in this release (and how partners clapped for Michael Nielsen when he showed them the new database indicator feature), my team does that much better than I. They've already provided for you a set of excellent blogs on the topic.

    Download a copy of Microsoft Dynamics NAV 2009 R2 on PartnerSource or CustomerSource and let us know what you think!

    Once again, thanks to all the customers and partners who've worked with us on this release, giving us continuous feedback about what we should work on. We hope you enjoy NAV 2009 R2 as much as we enjoyed building it. Finally, thanks to all the people at Microsoft working their butts off on Microsoft Dynamics NAV to deliver this release to you. A greater group of passionate folks I have not met!

    General Manager, Microsoft Dynamics NAV

  • Microsoft Dynamics NAV Team Blog

    NAV Design Pattern of the Week – the Hooks Pattern


    A new series of NAV Design Patterns is just starting. To make a good beginning, the first one is not chosen randomly. It is indeed a very powerful pattern – the “Hooks”, by Eric Wauters. It is also different from most patterns you’ve seen so far, in that it does not exist in the core product. “How can it be? A powerful NAV pattern which is not in NAV?”, you wonder.

    This is exactly the point of the Hooks. It is a partner pattern – something you, as a partner, can use, when you implement your customization. And if done correctly, it has the potential to make the next upgrade superfast.   

    Are you having a hard time installing update after update, rollup after rollup? Does it consume more resources than you had wished? Is the customization code entangled with the core product code, in such a way that each update requires complicated merges, with the developer trying to figure out which code goes where?

    To keep it short, here it is – the Hooks pattern. Most powerful when starting a new customization, as it can be implemented fully. It will keep things simple. As for the legacy customizations... it is still possible to use it, by refactoring key areas such as areas with the most update merge issues.

    Hooks Pattern

    by Eric Wauters (waldo), Partner-Ready-Software

    Meet the Pattern

    By minimizing the code in already existing application objects, you will make the upgrade process much easier, and all customization business logic will be grouped in new objects.  When using atomic coding, it will be very readable what is being customized on a certain place in an existing part of the application.

    To minimize the impact of customizations, the idea of hooks is:

    • First of all, name the places in the already existing code where customization is needed;
    • Second, place your business logic completely outside the already existing application code.

    Know the Pattern

    When doing development over years, by different developers with different mindsets, the standard codebase gets changed a lot, adding multiple lines of code, adding local and global variants, adding or changing keys, changing existing  business logic, … .  In other terms, the standard text objects are being changed all over the place.. .

    After years, it's not clear why a change was done, and what was the place where the change was intended to be done.  And the latter is quite important in an upgrade process, when code in the base product is being refactored: if the exact place of the posting of the Customer Entry is being redesigned to a separate number, the first thing I need to know, is that I did a certain change at the place: "where the posting of the Customer Entry starts".  The definition of that place, we call a "Hook".

    I recommend to use this concept on the following:

    • All objects of the default applications that need to be changed
    • On objects that should not hold any business logic (like tables, pages, XMLPorts)

    Use the Pattern

    Step 1 - if it doesn't exist yet - you create your Hook codeunit.  As the name assumes .. this is always a codeunit.  We apply the following rules to it:

    • One Hook always hooks into one object.  Which basically means that I will only declare this new codeunit in one other object (which is its parent object)
    • The naming convention is: The_Original_Object_Name Hook.  Naming conventions are important, just to find your mapped object, and also to be able to group the Hooks.

    Step 2, you  create the hook, which is basically a method (function) in your codeunit.  The naming is important:

    • The naming of the hook should NOT describe what it is going to do (So, examples like CheckMandatoryFields, FillCustomFields should not be used as a hook)
    • The naming of the hook should describe WHERE the hook is placed, not what the hook will be doing (as nobody is able to look into the future .. :-))
    • To help with the naming, it is a good convention to use the "On"-prefix for these triggers.  This way, it's very clear what are hooks, and what aren't..

    Step 3, it's time to hook it to its corresponding object and right place in the business logic of that object.  You do this by declaring your codeunit as a global in your object, and using the created hook function on its place in the business logic.  This way, these one-liners apply:

    • A Hook codeunit is only used once in one object only (its corresponding object)
    • A Hook (function) is used only once in that object.  As a consequence, changing the parameters has no consequence: you only need to change one function-call
    • The codeunit is declared as a global.  That exact global is the only custom declaration in the existing object .. Everything else is pushed to the hook-codeunit.

    Step 4, implement your business logic in the hook.  Do this in the most atomic way, as there is a good chance that this same hook is going to be used for other business logic as well.  Best is to use a one-line-function-call to business logic, so that the Hook Function itself stays readable.


    Suppose, we want to add business logic just before posting a sales document.  In that case, we have to look for the most relevant place, which is somewhere in the "Sales-Post" codeunit.  So:

    Step 1: create codeunit Sales-Post Hook:

    Step 2: create the hook function OnBeforePostDocument:

    Step 3: declare a global in the Sales-Post codeunit, called SalesPostHook.  Then,...

    Continue reading on the NAV Patterns Wiki...


    Best regards,

    The NAV Patterns team

  • Microsoft Dynamics NAV Team Blog

    Update Rollup 7 for Microsoft Dynamics NAV 2013 has been released


    Today we have released update rollup 7 for Microsoft Dynamics NAV 2013 (Build 35488).

    Update rollup 7 includes all application and platform hotfixes and regulatory features that have been released for Microsoft Dynamics NAV 2013 and includes hotfixes that apply to all countries and hotfixes specific to the following local versions:

    • AU – Australia
    • DE - Germany
    • DK - Denmark
    • FR - France
    • IT - Italy
    • NA – North America
    • NL – Netherlands
    • NZ – New Zealand
    • UK - United Kingdom

    Where to find update rollup 7

    You can download update rollup 7 from KB 2892427 -  Update Rollup 7 for Microsoft Dynamics NAV 2013 (Build 35488).

    The hotfixes that have been released since update rollup 6 are listed in KB 2892427. For a full list of all hotfixes included in the update rollup, see the following CustomerSource and PartnerSource pages:



    More Information

    For more information about update rollups for Microsoft Dynamics NAV 2013, see Announcement of new hotfix process for Microsoft Dynamics NAV 2013.

  • Microsoft Dynamics NAV Team Blog

    Cash Management in Microsoft Dynamics NAV 2013 R2 – More News!


    You read it here first! Microsoft Dynamics NAV R2 will deliver exciting new features to support cash management for our customers and prospects.

    What it really means for customers

    The bottom line is increased productivity – for all our customers – in almost any segment! The new Cash Management features in Microsoft Dynamics NAV R2 will automate and improve the cash management processes that are vital for all our customers regardless of the business they’re in.

    Consider this:

    • New Cash Management functionality includes easy registration of payments to ensure faster business processes with fewer human errors.
    • You can import electronic payment files from banks and use them as basis for payments registrations. (In Denmark for Danish banks out of the box. Other countries will require minor configurations)
    • Bank Reconciliation is possible as both a manual and an automated process, with the option to import bank statements from banks and reconcile automatically. A simple tool can be used to set up automation, handle exceptions and complete the reconciliation process.
    • Bank Statements can be imported from 3rd party providers. The same functionality will allow partners to build their own integration to banks, meaning a free choice of providers.

    What features are introduced to enable this?


    A new feature is introduced that enables the user to export payment data to an electronic bank file in SEPA compliant format. This gives the user the possibility to integrate electronically with any bank in the Single European Payment Area and get higher efficiency in the payment process end-to-end.

    Also, when payment instructions to the bank are managed directly in the system the user gets better control over the payment process and the ability toenhance cash flow due to SEPA rules about dates.


    A new feature called SEPA Direct Debit Collections, which provides an efficient way to handle customer’s payment collections through your preferred bank in the Single European Payment Area (SEPA) with less manual entry of data and effective mandate handling.

    The feature allows users to collect money from their customers in a seamless connected way with the invoicing process, minimizing the order to cash lead time and increasing their cash management efficiency.


    A new tool that enables partners to import SEPA compliant schemas (ISO 20022) into Microsoft Dynamics NAV and export the desired xml tags in an xmlport ready format. This gives the partner an excellent starting point for building up new xmlport to handle SEPA format variations for its customers.

    Also, when handling the xml schema, relevant information about each tag is displayed enabling filtering mandatory tags and attributes.

    How and when you can learn more on MSDN

    We are working on a number of knowledge articles right now and plan to have these ready for you soon on MSDN

    Hear more first-hand at DIRECTIONS!

    Don’t miss the upcoming Direction events. Join us to hear how Microsoft Dynamics NAV 2013 R2 offers new cash management features in a harmonized way across country versions. We will demonstrate the new features and you will learn how you can take it to your markets - enabling you to go for volume by having more application features to offer as standard.

    Stay tuned for more info on the NAV team blog space, Yammer, MSDN, Directions and more.

    Kind regards

    Your Cash Management team

  • Microsoft Dynamics NAV Team Blog

    Creating URLs to Microsoft Dynamics NAV Clients


    The URL builder function, GETURL, is released in Microsoft Dynamics NAV 2013 R2 to reduce coding time for developers who need to create various URL strings to run application objects in either the win client, the web client, or on web services. In addition, the GETURL function makes multitenancy features more transparent to C/AL developers.


    Ever had to construct win client URLs like the one below?


    Today, Microsoft Dynamics NAV also provides a web client. This means that you must update your code to construct web client URLs too. What about multitenancy? The URL Builder should know if it is running in a multitenant setup and it should know how to choose the right tenant. What about maintaining this code?

    The good news is that GETURL has been introduced to handle all URL building for you.

    GETURL automatically handles:

    • Multitenancy
    • Correct URL format for each client
    • Publicly accessible hostnames.


    The format is:

    [String :=] GETURL(ClientType[, Company][, Object Type][, Object Id][, Record])


    • Client Type can be: Current, Default, Windows, Web, SOAP, or OData. This enables a range of scenarios for the C/AL developer, such as moving to the web client without changing code to decide where the URL should point to. This is done either by setting Client Type to Current, and just ensuring that web is used to invoke the link creation, or by setting Client Type to Default and changing its value to Web when it is ready to move to the web platform.
    • Object Type and Object ID define the type of the application object to run (Table, Page, Report, Codeunit, Query, or XMLport) and its ID.
    • Record specifies the actual data to run the URL on, such as:

    Vendor.GET("Account No.");


    Note: It is currently not possible to set filters on the record that you sent as a last parameter to the GETURL function. However, it is possible to write your own code to compute and append the filter string to the URL that is created by the GETURL function.

    The server name and instance are extracted automatically by GETURL and do not need to be specified by the C/AL developer. Furthermore, the multitenancy setup is transparent to the C/AL developer. No multitenancy parameters are specified when you call GETURL, because the function knows from the server setup if it is running in a multitenant environment and if so, it will add a string like "&tenant=MyTenant" to the URL.

    When to Use

    The GETURL function can generally be used every time a URL must be created. The following are some scenarios where the function is particularly useful.

    • Document approvals. For more information, see the “NAV Usage Example” section.
    • Reports containing drill-down links. (Beware of the resource cost of adding a new URL element to the Report dataset.)
    • When planning to write code for, or migrate to, various display targets (Microsoft Dynamics NAV Windows client, Microsoft Dynamics NAV web client, Microsoft Dynamics NAV web services) without having to explicitly specify which client to use.

    Examples of Usage

    The following are examples of calls to GETURL and their corresponding return value:











    GETURL(CLIENTTYPE::Current) ie. When running this code on a Win client session


    GETURL(CLIENTTYPE::Default) ie. When the Server config key DefaultClient is set to Windows







    dynamicsnav://MyServer:7046/DynamicsNAV71/NONEXISTING Corp/






    https://navwebsrvr:443/DynamicsNAV71_Instance1/Webclient?company=NONEXISTING Corp






    http://MyServer:7048/DynamicsNAV71/OData/Company('NONEXISTING Corp')






    http://MyServer:7047/DynamicsNAV71/WS/NONEXISTING Corp/Services













    GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::Page,27) ie. When the Web Service is published


    GETURL(CLIENTTYPE::OData,COMPANYNAME,OBJECTTYPE::Query,9150)  ie. When the Web Service is published


    GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::Page,27)  ie. When the Web Service is published


    GETURL(CLIENTTYPE::SOAP,COMPANYNAME,OBJECTTYPE::Codeunit,5065)  ie. When the Web Service is published
















    If the GETURL function is called with invalid parameters, it will return an empty string. In that case, you can find the related error text by calling the GETLASTERRORTEXT function.

    Function Call

    Error Message


    The specified object type parameter for the GetUrl function is not valid.


    The specified object type parameter for the GetUrl function is not valid.


    The specified object type parameter for the GetUrl function is not valid.


    The specified object type parameter for the GetUrl function is not valid.


    The specified object type parameter for the GetUrl function is not valid.


    The Page object, 27, that is specified for the GetUrl function has not been published in the Web Services table.


    The specified object type parameter for the GetUrl function is not valid.


    The specified object type parameter for the GetUrl function is not valid.


    The Query object, 9150, that is specified for the GetUrl function has not been published in the Web Services table.


    The specified object type parameter for the GetUrl function is not valid.


    The specified object type parameter for the GetUrl function is not valid.


    The Page object, 27, that is specified for the GetUrl function has not been published in the Web Services table.


    The specified object type parameter for the GetUrl function is not valid.


    The Codeunit object, 5065, that is specified for the GetUrl function has not been published in the Web Services table.


    The specified object type parameter for the GetUrl function is not valid.


    The specified object type parameter for the GetUrl function is not valid.


    You cannot specify a record parameter for the GetUrl function when the object type is SOAP

    NAV Usage Example

    The following example shows how to use the GETURL function in codeunit 440 to ensure that the notification mail in Document Approvals can link to both the Microsoft Dynamics NAV Windows client and the Microsoft Dynamics NAV web client:

    This resulting UI looks as follows.

    The first link opens the approval document in the Microsoft Dynamics NAV Windows client. The second link (Web view) opens the same document in the Microsoft Dynamics NAV web client.


    Best regards,

    Mike Borg Cardona, Bogdana Botez, and the Microsoft Dynamics NAV team

Page 5 of 44 (650 items) «34567»