• Microsoft Dynamics NAV Team Blog

    Application Test Toolset for Microsoft Dynamics NAV 2013

    • 10 Comments

    We recently shipped the Application Test Toolset for Microsoft Dynamics NAV 2013.

    The supplement is applicable to the following country releases of Microsoft Dynamics NAV 2013:

    W1, AU, CA, DE, DK, ES, FR, GB, IN, IT, MX, NL, NZ, SE and US

    The supplement contains the following per country:

    • Tools for managing and executing tests, capturing code coverage information, and selecting relevant tests out of available tests.
    • Between 7,000 – 9,000 real regression tests that we run, not dumbed-down sample tests.
    • Helper libraries for improving test development through reusing common functionality.
    • Searchable documentation of helper libraries with examples of how to use library functionality.

    You may attempt to apply the W1 version to other country versions, but you should expect parts of the toolset to not work.

    Installation

    To install the supplement, do the following:

    1. Download the supplement from PartnerSource here.
    2. Extract the content.
    3. Import the FOB file found under your corresponding country version folder. For example: .\AppTestToolsetNAV2013\DE\AppTestToolsetNAV2013-DE.fob
    4. After experimenting with the toolset, don’t forget to fill out the survey form and send it to Microsoft. We really appreciate your feedback and we rely on it to improve future versions of the toolset.

    How Do I Use This?

    The simplest way to make use of this supplement is to run the Test Tool page (130021) directly from the development environment. This launches the following page:

    Click Get Test Codeunits and then select All Test Codeunits.

    After Microsoft Dynamics NAV finishes loading all test codeunits, they are displayed on the Test Tool page. To run them, click the Run action and then select All.

    It will take about 1 – 2 hours depending on your machine and the setup to run all tests. When the run is completed it will show the results in the Test Tool page:

    Any changes done to the database through running of tests from the Test Tool are automatically rolled back using the Test Isolation testability feature of Microsoft Dynamics NAV 2013. (See the Additional Resources section in this post.)

    During typical development, it is unacceptable to have to wait hours to get results from tests, which is why we have built an advanced test selection feature to help identify the relevant tests. (See the Test Selection section in this post.)

    Alternatively, you can run individual tests or codeunits by selecting them and choosing either Active Line or Active Codeunit after you click the Run action.

    If any test fails, you can attach a debugger session and re-run the failing test. The debugger will then break at the line where the test failed and you will be able to inspect the call stack and examine variables to determine the underlying cause of the failure.

    Extending the Toolset With Your Own Tests

    After you have written your first test codeunit, you can easily integrate it into the tools we provide in this supplement.

    To include your own tests, in the Test Tool page, simply run the page from the development environment and click the action Get Test Codeunits and choose Select Test Codeunits. This will display a page listing all available test codeunits, including your own:

    Select the codeunits you would like to add to the tool and press OK. The new test codeunits appear at the bottom of the Test Tool list, and you can now select them and run them just like any of the tests we included.

    Again, Test Isolation prevents your tests from persisting changes to the database. During development it may be beneficial to actually see the output produced by the tests. It is possible to disable Test Isolation just by running the test codeunit directly from the development environment, however, instead we recommend attaching a debugger session, breaking at the test entry point, then stepping through test execution and inspecting variables to determine if your test is behaving as expected.

    Speeding Up Development of Your Own Tests

    The tests that we have developed are built on top of a layer of libraries that contain helper functionality to automate many aspects of Microsoft Dynamics NAV. For example, the library named Library – Sales contains functionality related to working with customers and sales documents, including creating new customers, sales headers, sales lines and posting sales documents. The library is extensive and has functionality in many areas of the product, such as finance, service, jobs, warehousing, inventory, etc.

    Instead of re-inventing the wheel when developing your own tests, we highly suggest that you look into our existing helper functionality for functions you can leverage.

    To help you find your way around the libraries, we have shipped a Microsoft Compiled HTML Help file (*.chm), which is bundled together with the .fob file you installed. When you open the .chm file, you are prompted with the following window:

    This lists all our libraries and the functions inside them. However, normally you don’t know which library to look for, You can search it from the Search tab. Try searching for "finance charge memo" and you will have a couple of choices to pick from:

    Code Coverage Tools

    Code coverage is the means of being able to track which part of the application code has been exercised during some activity. In Microsoft Dynamics NAV, code coverage is recorded by AL code line and in addition to knowing if a code line was exercised it also records the number of times it was recorded.

    The code coverage activity that we record can be any interaction with Microsoft Dynamics NAV, be it manual user interaction, automated test execution, NAS, Web services, etc. You can, of course, record code coverage of your own tests exercising your own objects.

    The toolset includes a page (130002), Code Coverage List, which you can use to track code coverage. Run the page from the development environment:

    From this page you can start/refresh/stop the code coverage recorder. If you click the Start action, the code coverage engine is turned on and code coverage is captured. However, you will not be able to see any updated information before you click either Refresh or Stop, at which time you are presented with the code coverage information:

    The information contains coverage of objects, triggers/functions and individual lines (code and empty) as determined by the column Line Type. Only lines of type Code can have coverage. Lines of type Trigger/Function show the average coverage of all code lines in the trigger/function. Lines of type Object show the average coverage of all code lines inside the object.

    From the above picture, you can read that the activity exercised 33.93% of the Currency table (4). It covered 100% of the OnModify trigger and that comes from 100% of a single Code line.

    It is often desirable to filter on Line Type = Object to first get a high-level overview of the coverage result:

    Then from here, you can filter to look at individual objects and expand the Line Type filter to include triggers/functions as well:

    This way you can drill-down into the results starting from a high-level view going to a low-level view.

    Note #1: Code coverage is recorded globally for all sessions when using this tool, so make sure you are running in a controlled environment so you don’t have any activity from unaccounted sessions.

    Note #2: Only objects that are touched by the activity are recorded, meaning the coverage of any object not in the list is implied to be zero. If you would like to force the recorder to include specific objects even if they are not covered, you can use
    the Load objects action and select the relevant objects from the subsequent page. This forces the code coverage engine to load these objects and provide information on even when no lines are covered.

    Test Selection

    Now that we have all the building blocks in place, I’d like to talk about an advanced feature we included with the tooling.

    As mentioned previously, having to wait hours to run all tests is not feasible from a development point of view. Therefore we shipped the Test Selection, which helps you narrow the set of tests down to the relevant tests.

    The feature works by analyzing the code coverage data from individual test codeunits and comparing it to the set of objects that have the Modified field set to Yes in the database.

    To use this feature, you run the Test Tool page and go to the Actions tab and click Import/Export Test Map action. On the request page, make sure the direction is Import and click OK. Browse to the bundled "AppTestToolsetNAV2013-<country
    code>-Map.txt" file and import the file. This will take a couple of seconds. After it is done, click the Get Test Codeunits action. The prompt will now include a third option:

    Select this third option and the tool will automatically detect the relevant tests to run and add them to your current suite.

    Note #1: In typical circumstances you would want to make sure your suite is empty before using this feature.

    Note #2: There is a small risk this feature will not identify all relevant tests in unusual circumstances. Thus we strongly recommend running the full regression suite before shipping anything to the customer.

    This feature also integrates with you own tests. Once enabled (by loading the Test Map), the information will auto-update when any test is run – including your own tests. This means that you can load the map, run your tests and now export the map to another text file. You can then load the new map into another database and the test selection feature will now be able to suggest your own tests based on modified objects in this other database. If your test codeunit is not present in the database, you will be prompted with a list of missing test codeunits that could not be added. Import the missing test codeunits into the database and re-run the test selection feature.

    Additional Resources

    -Simon Ejsing

  • Microsoft Dynamics NAV Team Blog

    It IS possible to instantiate the Visual Studio bridge.

    • 10 Comments

    Solution developers will often have different versions of Dynamics NAV installed on a single machine for their development environment. The way this is often implemented is to fully install the latest version and simply copy the Classic Client binary files for earlier versions into separate folders so you have something like this:

    NAV 2009 R2 fully installed with an R2 SQL Server database
    C:\NAVCLIENTS\NAV 40 SP3\ClassicClient (containing NAV binary files. A NAV 4.0 SP3 database is also accessible on the machine)
    C:\NAVCLIENTS\NAV 50 SP1\ClassicClient (similar setup to above)
    C:\NAVCLIENTS\NAV 2009\ClassicClient
    C:\NAVCLIENTS\NAV 2009 SP1\ClassicClient

    This approach has been working for solution developers for some time now. However, after installing Dynamics NAV 2009 R2, if you then try to view the Layout for an NAV 2009 SP1 Report you will get the following error:

    ---------------------------
    Microsoft Dynamics NAV Classic
    ---------------------------
    It is not possible to instantiate  the Visual Studio bridge.
    ---------------------------
    OK  
    ---------------------------

    This is due to a design change in NAV 2009 R2 which uses the .NetBridge rather than the old Visual Studio bridge component. However, the Visual Studio bridge files are included with the binaries in the NAV 2009 SP1 Classic Client folder so you can avoid the above error by running REGASM.EXE to register the DLL. The REGASM.EXE is included in the .Net Framework folder so executing the following command from within the NAV 2009 SP1 Classic Client folder should do the trick:

    C:\Windows\Microsoft.NET\Framework\v2.0.50727\regasm.exe Microsoft.Dynamics.Nav.VisualStudioBridge.DLL

    Of course, the REGASM.EXE may be located in a different path in your machine so alter the above command line as required.

    Gerard Conroy
    Microsoft Dynamics NAV Support

  • Microsoft Dynamics NAV Team Blog

    Running classic reports in RTC (RUNMODAL and a few other things)

    • 10 Comments

    Just a few points about running classic reports from RTC, based on common support scenarios:


    RUNMODAL (Not possible)

    RTC runs classic reports (reports with no RDL Layout) by starting the report engine from a classic client. However, RTC is not able to run classic reports MODALLY. RUNMODAL as opposed to just RUN means that execution of the  next line of C/AL code waits until the report has completed. Of course RTC reports which DO have a layout can run MODALLY without any problems.

    So Report.RUNMODAL on a classic report from RTC does exactly the same as Report.RUN, i.e. RTC will launch the classic report engine but not wait for the report to finish before executing the next line of code. In most cases this doesn't matter. But the challenge is when the next line of code dependeds on the report having completed, for example to email the report, convert it to pdf, write back a result of the report to the database, or something else.

     

    Running batches of classic reports (Improvement)

    The good news is that there has been a few small other improvements relating to running classic reports from RTC. When the classic client closes, it updates a few files like the .zup file, and in the case of breakpoints having been used, also NaviBP.xml as described here:
    http://msdn.microsoft.com/en-us/library/dd355196.aspx
    In case we launched a batch of classic reports, one instance of the classic report engine would start up for each report. And each instance could overwrite each other's files, leading to error messages like this:

    You cannot use the file C:\Users\[USER]\AppData\Roaming\fin.zup  because it is already in use.

    and


    Microsoft Visual C++ Runtime Library
    Runtime Error!

    Program: C:...

     This application has requested the Runtime to terminate it in an unusual way.
    Please contact the application's support team for more information. 

    But with KB 2398170 (build 31587) the behaviour is changed, so that now when the classic client closes the report engine, it willl 1) only try to update the .zup file, and 2) not try to update naviBP.xml at all, avoiding the error messages mentioned above.

     
    Licenses (No, it doesn't consume a license)

    When you run a classic report from RTC, this does NOT consume a user license. If you watch the Session table while a classic report is running, you will see that a new session has connected, but with "Application Name" = '111'. In this way the system knows not to count it as a normal NAV client, so it will not count as a concurrent session.

     

     

    Lars Lohndorf-Larsen

    Microsoft Dynamics UK

    Microsoft Customer Service and Support (CSS) EMEA

  • Microsoft Dynamics NAV Team Blog

    Using XMLports With Web Services

    • 10 Comments

    As a follow-up on my recent webcast (found HERE), here is the general walkthrough of how to create an XMLport and use it for sending data to NAV.

    First, what we want to do is create our XMLport and make sure it has the elements and values that we want.

    XMLPort

    For the root element, I have set maxOccurs = 1 to avoid any confusion.
    For the general XMLport, the UseDefaultNamespace and the DefaultNamespace values have been edited as seen below.

    SS02

    Other than that, I have no code on my XMLport, but naturally, anything goes that would work on a regular XMLport. Now to the Codeunit:


    ImportDim(VAR DimImport : XMLport DimImport) Return : Text[30]
    DimImport.IMPORT;
    EXIT('Import Run');

    So basically we’re telling the XMLport to run an import and we’re returning to the Web Service that we’ve run. All we need to do now is expose the Web Service using Form 810:

    SS03

    Remember that the actual name of the codeunit does not have to match that of the service name here.

    So now we move over to Visual Studio and start working with what we have. The first thing we’ll notice is that the WSDL matches our XMLport.

    SS04

    What we see is both the RootDimensions element which consists of multiple Dimension elements. From there, we can see the definition of the Dimension element the fields we’ve chosen to expose.

    When creating a new project, we will go with a Windows Forms project this time.

    SS05

    And from there we will start off by adding a web reference to http://localhost:7047/DynamicsNAV/WS/Codeunit/DimensionImport .

    The details on how to add a web reference can be found in the Developer and IT Pro Documentation.

    On my new form, I have created two input boxes for the Code and Name of the dimension and a Create button.

    SS06

    And then we have the code on the Create button, along with helpful comments:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms; 

    namespace
    NAV2009SP1WSDemo

        using WSDI; 
        public partial class Form1 : Form 
        {    

     

     

     

            public Form1() 
           
                InitializeComponent(); 
           
     
            private void button1_Click(object sender, EventArgs e) 
           
                //Make sure the ResultLabel doesn't have any text on multiple runs 
                ResultLabel.Text = ""

               
    //Create a WS reference instance, set credentials and define the company by specifying the URL. 
                DimensionImport NAVImport = new DimensionImport(); 
                NAVImport.UseDefaultCredentials = true
                NAVImport.Url = "http://localhost:7047/DynamicsNAV/WS/CRONUS%20International%20Ltd/Codeunit/DimensionImport"
                
                //First we create our root element 
                RootDimensions RootDim = new RootDimensions();

     

     

     

                //Then we create a List to handle our (possible) multiple dimensions 
                List<Dimension> DimList = new List<Dimension>();

     

     

     

                //And then we create a single dimension 
                Dimension Dim = new Dimension();  

     

                if (dimInputCode.Text != "" && dimInputName.Text != ""
               
                    //We assign the values from our textboxes to the single dimension 
                    Dim.DimensionCode = "AREA"
                    Dim.Code = dimInputCode.Text; 
                    Dim.Name = dimInputName.Text;

     

     

     

                    //Then we add the single dimension to our list 
                    DimList.Add(Dim);  

     

                    //To get the list of dimensions "attached" to the root element, we use the following
                    RootDim.Dimension = DimList.ToArray(); 
                    try 
                   
                        //Then we send to NAV and show our result 
                        ResultLabel.Text = NAVImport.ImportDim(ref RootDim);

     

     

     

                   
                    catch (Exception ex) 
                   
                        //Show a possible exception 
                        ResultLabel.Text = ex.ToString(); 
                   
               
                else 
               
                    //Make sure there are values 
                    ResultLabel.Text = "Both values must be filled"
               
            
        }
    }

    Our wonderful application is now ready to run and all we have to do is press F5:

    SS07

    We have now created our XMLport, exposed it using a codeunit and set data into it from a form based application.

    Lars Thomsen

    Microsoft Customer Service and Support (CSS) EMEA

  • Microsoft Dynamics NAV Team Blog

    Cumulative Update 9 for Microsoft Dynamics NAV 2013 R2 has been released

    • 10 Comments

    Cumulative update 9 includes all application and platform hotfixes and regulatory features that have been released for Microsoft Dynamics NAV 2013 R2. 

    The cumulative update includes hotfixes that apply to all countries and hotfixes specific to the following local versions:

    • AU - Australia
    • AT - Austria
    • BE - Belgium
    • CH – Switzerland
    • CZ Czech Republic (New)
    • DE - Germany
    • DK - Denmark
    • ES - Spain
    • FI  - Finland
    • FR - France
    • IS - Iceland
    • IT - Italy
    • NA - North America
    • NL - Netherlands
    • NO - Norway
    • NZ - New Zealand
    • RU – Russia
    • SE - Sweden
    • UK - United Kingdom

    This cumulative update also introduces new application merge utilities: A new set of Windows PowerShell cmdlets that can help you through code upgrade.

    You can use the new cmdlets to modify application object source files in the Microsoft Dynamics NAV 2013 R2 Development Shell, or by importing the Microsoft.Dynamics.NAV.Model.Tools.psd1 module into the Windows PowerShell Integration Script Environment (ISE). The new application merge utilities install when you choose the Developer option in Microsoft Dynamics NAV 2013 R2 Cumulative Update 9 Setup, or if you add the development environment to another installation option.

    For more information, see the MicrosoftDynamicsNAV2013R2CU9_MergeApplicationObjectSourceFiles.pdf whitepaper, which is attached to this blog post. We will also write about the new cmdlets here on the blog.

    Where to find cumulative update 9

    You can download cumulative update 9 from KB 2977473 – Cumulative Update 9 for Microsoft Dynamics NAV 2013 R2 (Build 37221).

    For a full list of all hotfixes included in cumulative updates for Microsoft Dynamics NAV 2013 R2, see the following CustomerSource and PartnerSource pages: 

    CustomerSource:

    PartnerSource

    More Information

    For more information about cumulative updates for Microsoft Dynamics NAV 2013 R2, see Announcement of update rollups for Microsoft Dynamics NAV 2013 R2

    For a list of all release cumulative updates, see Released Cumulative Updates for Microsoft Dynamics NAV 2013 R2.

  • Microsoft Dynamics NAV Team Blog

    Cumulative Update 10 for Microsoft Dynamics NAV 2013 R2 has been released

    • 9 Comments

    Cumulative update 10 includes all application and platform hotfixes and regulatory features that have been released for Microsoft Dynamics NAV 2013 R2.

     The cumulative update includes hotfixes that apply to all countries and hotfixes specific to the following local versions:

    •   AU - Australia
    •   AT - Austria
    •   BE - Belgium
    •   CH – Switzerland
    •   CZ – Czech Republic
    •   DE - Germany
    •   DK - Denmark
    •   ES - Spain
    •   FI  - Finland
    •   FR - France
    •   IS - Iceland
    •   IT - Italy
    •   NA - North America
    •   NL - Netherlands
    •   NO - Norway
    •   NZ - New Zealand
    •   RU – Russia
    •   SE - Sweden
    •   UK - United Kingdom

    License Versioning

    Microsoft Dynamics NAV 2013 R2 Cumulative Update 10 introduces license key versioning to Microsoft Dynamics NAV. Observe the following specifications:

    • Microsoft Dynamics NAV 2013 R2 license keys will continue to be backward compatible with Microsoft Dynamics NAV 2013 instances.
    • Microsoft Dynamics NAV 2013 license keys cannot not be used with Microsoft Dynamics NAV 2013 R2 instances. Accordingly, newly issued Microsoft Dynamics NAV 2013 license keys will not work with Microsoft Dynamics NAV 2013 R2 CU10 (or later) instances.
    • Microsoft Dynamics NAV 2013 and Microsoft Dynamics NAV 2013 R2 license keys are not forward compatible with Microsoft Dynamics NAV 2015 instances.

     More details about license versioning will be made available in the October 2014 release of the Microsoft Dynamics Perpetual Licensing Guide.

    Where to find cumulative update 10

    You can download cumulative update 10 from KB 2984452 – Cumulative Update 10 for Microsoft Dynamics NAV 2013 R2 (Build 37563). We listed a different build number when this blog post published the first time, and we apologize for the resulting confusion. the correct build number is 37563.

    For a full list of all hotfixes included in cumulative updates for Microsoft Dynamics NAV 2013 R2, see the following CustomerSource and PartnerSource pages:

    CustomerSource:

         *  Overview of Released Application Hotfixes for Microsoft Dynamics NAV 2013 R2

         *  Overview of Released Platform Hotfixes for Microsoft Dynamics NAV 2013 R2

    PartnerSource

         *   Overview of Released Application Hotfixes for Microsoft Dynamics NAV 2013 R2

         *  Overview of Released Platform Hotfixes for Microsoft Dynamics NAV 2013 R2

    More Information

     For more information about cumulative updates for Microsoft Dynamics NAV 2013 R2, see Announcement of update rollups for Microsoft Dynamics NAV 2013 R2.

     

  • Microsoft Dynamics NAV Team Blog

    Cumulative Update 7 for Microsoft Dynamics NAV 2013 R2 has been released

    • 9 Comments

    Cumulative update 7 includes all application and platform hotfixes and regulatory features that have been released for Microsoft Dynamics NAV 2013 R2. 

    The cumulative update includes hotfixes that apply to all countries and hotfixes specific to the following local versions:

    • AU - Australia
    • AT - Austria
    • BE - Belgium
    • CH - Switzerland
    • DE - Germany
    • DK - Denmark
    • ES - Spain
    • FI  - Finland
    • FR - France
    • IS - Iceland
    • IT - Italy
    • NA - North America
    • NL - Netherlands
    • NO - Norway
    • NZ - New Zealand
    • RU – Russia
    • SE - Sweden
    • UK - United Kingdom

    Where to find cumulative update 7

    You can download cumulative update 7 from KB 2964528 – Cumulative Update 7 for Microsoft Dynamics NAV 2013 R2 (Build 36703 - our apologies for originally posting the wrong build number).

    For a full list of all hotfixes included in cumulative updates for Microsoft Dynamics NAV 2013 R2, see the following CustomerSource and PartnerSource pages: 

    CustomerSource:

    PartnerSource

    More Information

    For more information about cumulative updates for Microsoft Dynamics NAV 2013 R2, see Announcement of update rollups for Microsoft Dynamics NAV 2013 R2

  • Microsoft Dynamics NAV Team Blog

    How to get a Dynamics NAV report with a Web Service

    • 9 Comments

    1. Create a new codeunit. In this scenario we will call this codeunit "CUWebReport" with ID 50000

    2. Navigate to "C/AL Globals" and create a function called "GenerateReport"

    image 

    3. Select "Locals"

    4. Select the "Return Value" tab

    5. Set "Return Type"=Text and "Length"=100

    image

    6. With this completed close "C/AL Locals" window.

    7. Now with "C/AL Globals" windows active again. Select "Variables" tab.

    8. Create a variable called "filename" with "Data Type"=Text and "Length"=100

    image

    9. Now let's add the following code to this codeunit:

    filename := 'C:\inetpub\PdfDocuments\';
    filename += FORMAT(CREATEGUID);
    filename := DELCHR(filename, '=', '{-}');
    filename += '.pdf';
    REPORT.SAVEASPDF(111,filename);
    EXIT(filename);

    image

    10. Save and compile the codeunit.

    11. Now it's time to expose this codeunit as Web Service. Navigate to "Administration/IT Administration/General Setup/Web Services"

    12. Select codeunit 50000 and give this a service name, we use "Get_PDF_Report"

    image

    13. Now it is time to verify that we can see this web service. Open this URL  http://localhost:7047/DynamicsNAV/WS/services.

    You should now see this message in your browser, and your Web Service can now be called :

    image

    If you don't see this message, you might want to check that  the service "Microsoft Dynamics NAV Business Web Services" has been started.

    14. Now it is time to call the Web Service, in this example we use Microsoft Visual Web Developer 2005. And we use the following code to call the Web Service:

    Partial Class _Default
        Inherits System.Web.UI.Page

        Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim service As localhost.Get_PDF_Report = New localhost.Get_PDF_Report()
            service.UseDefaultCredentials = True
            service.Url = "
    http://localhost:7047/DynamicsNAV/WS/CRONUS_International_Ltd/Codeunit/Get_PDF_Report"
            Response.ContentType = "application/pdf"
            Dim pdfFileName As String = service.GenerateReport()
            Response.TransmitFile(pdfFileName)

        End Sub
    End Class

    But how to consume this Web Service is not in scope for this blog, so we suggest you have look our online help how to consume a Web Service from NAV 2009.

    Online help found here: http://msdn.microsoft.com/en-us/library/dd339004.aspx

    15. Now also remember to impersonate your web servers application to an appropriate Dynamics NAV user.

    16. After compiling a running our project we then get this button in our browser.

    image

    17. When activating this button, we get the report specified in Codeunit 50000 displayed as an PDF file in our browser.

    image

    Conclusion, now you can give this URL to people who don't have access to Dynamics NAV, and they can execute the report when they see a need for this.

    Thanks,

    Torben Meyhoff, SDE & Claus Lundstrøm, Program Manager, Microsoft Dynamics NAV

  • Microsoft Dynamics NAV Team Blog

    How to create/read xml file from Microsoft Dynamics NAV without using xmlports

    • 9 Comments

    Periodically we receive support requests about XMLport errors, which really are missing features in xmlport's functionality.
    However most of these requests are rejected because: xmlports are not supposed to fulfill all possible xml standard scenarios.
    So there always will be xml file which can't be created or readed by NAV xmlport.
    Possible workaround could be to use XML DOM automations.

    Create it by codeunit:

    ----------------------------------------

     OBJECT Codeunit 50052 xml create
    {
      OBJECT-PROPERTIES
      {
        Date=03/24/10;
        Time=[ 1:33:31 PM];
        Modified=Yes;
        Version List=;
      }
      PROPERTIES
      {
        OnRun=BEGIN
                CREATE(xmlDoc);
                xmlMgt.SetNormalCase;
                xmlProcessingInst:=xmlDoc.createProcessingInstruction('xml','version="1.0" encoding="UTF-8" standalone="yes"');

                CurrNode := xmlDoc.appendChild(xmlProcessingInst);
                CurrNode := xmlDoc.createElement('soapenv:Envelope');
                CurrNode := xmlDoc.appendChild(CurrNode);


                xmlMgt.AddAttribute(CurrNode,'xmlns:soapenv','http://schemas.xmlsoap.org/soap/envelope/');
                xmlMgt.AddAttribute(CurrNode,'xmlns:mbs','http://www.microsoft.com/mbs/xml');

                xmlMgt.AddElement(CurrNode,'soapenv:Header','','soapenv',NewChild);
                  CurrNode:=NewChild; //One level deeper
                  xmlMgt.AddElement(CurrNode,'soapenv:Body','','soapenv',NewChild);
                       CurrNode:=NewChild; //one level deeper
                       xmlMgt.AddElement(CurrNode,'mbs:enumeration','','mbs',NewChild);
                            CurrNode:=NewChild; //one level deeper
                            xmlMgt.AddElement(CurrNode,'mbs:table','Customers','mbs',NewChild);

                         recCustomer.SETRANGE("No.", '10000','20000'); //Filter only few records
                         IF recCustomer.FINDFIRST THEN BEGIN
                           REPEAT
                            vName   :=recCustomer.Name;
                            vNo     :=recCustomer."No.";
                            vContact:=recCustomer.Contact;
                              recCustomer.CALCFIELDS("Balance (LCY)");
                              vBalance:= FORMAT(recCustomer."Balance (LCY)");
                            vSPcode :=recCustomer."Salesperson Code";


                            xmlMgt.AddElement(CurrNode,'mbs:Customer','','mbs',NewChild);
                                  CurrNode1:=NewChild; //One level deeper, but keep current level too
                                  xmlMgt.AddElement(CurrNode1,'mbs:CustomerAuthentication','','mbs',NewChild);
                                         CurrNode2:=NewChild; //One level deeper to sublevel
                                         xmlMgt.AddElement(CurrNode2,'mbs:No',vNo,'mbs',NewChild);
                                         xmlMgt.AddElement(CurrNode2,'mbs:Name',vName,'mbs',NewChild);

                                  xmlMgt.AddElement(CurrNode1,'mbs:CustomerData','','mbs',NewChild);
                                         CurrNode2:=NewChild; //One level deeper to sublevel
                                         xmlMgt.AddElement(CurrNode2,'mbs:Balance',vBalance,'mbs',NewChild);
                                         xmlMgt.AddElement(CurrNode2,'mbs:SalespersonCode',vSPcode,'mbs',NewChild);
                                         xmlMgt.AddElement(CurrNode2,'mbs:Contacts','','mbs',NewChild);
                                             CurrNode1:=NewChild;//One level deeper
                                             xmlMgt.AddElement(CurrNode1,'mbs:Contact',vContact,'mbs',NewChild);


                            CLEAR(vName);
                            CLEAR(vNo)  ;
                            CLEAR(vContact);
                            CLEAR(vBalance);
                            CLEAR(vSPcode);

                           UNTIL recCustomer.NEXT=0;


                           xmlDoc.save('D:\xmlFile.xml');
                           CLEARALL;
                           MESSAGE('xmlFile.xml is created');
                         END;
              END;

      }
      CODE
      {
        VAR
          xmlDoc@1000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.DOMDocument";
          CurrNode@1003 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMNode";
          CurrNode1@1005 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMNode";
          CurrNode2@1013 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMNode";
          NewChild@1004 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMNode";
          xmlProcessingInst@1001 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF89-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMProcessingInstruction";
          xmlMgt@1002 : Codeunit 6224;
          "---- Variables----"@1006 : Integer;
          recCustomer@1012 : Record 18;
          vName@1007 : Text[30];
          vNo@1008 : Text[30];
          vContact@1009 : Text[30];
          vBalance@1010 : Text[30];
          vSPcode@1011 : Text[30];

        EVENT xmlDoc@1000::ondataavailable@198();
        BEGIN
        END;

        EVENT xmlDoc@1000::onreadystatechange@-609();
        BEGIN
        END;

        BEGIN
        END.
      }
    }

    ---------------------------------------

    And can be read by codeunit: 

    OBJECT Codeunit 50050 xml read
    {
      OBJECT-PROPERTIES
      {
        Date=03/24/10;
        Time=12:25:26 PM;
        Modified=Yes;
        Version List=;
      }
      PROPERTIES
      {
        OnRun=BEGIN
                ffile.OPEN('D:\XmlFile.xml'); //this must be your file name
                ffile.CREATEINSTREAM(strInStream);

                IF ISCLEAR(xmldomDoc) THEN CREATE(xmldomDoc);

                xmldomDoc.load(strInStream);

                xmlNodeList1 := xmldomDoc.getElementsByTagName('mbs:Customer');

                ii:=xmlNodeList1.length();

                FOR i:=0 TO xmlNodeList1.length()-1 DO BEGIN
                 xmldomElem1:= xmlNodeList1.item(i); //mbs:Customer
                 IF xmldomElem1.hasChildNodes() THEN
                    BEGIN
                      xmlNodeList2:= xmldomElem1.childNodes();
                      IF NOT ISCLEAR(xmlNodeList2) THEN
                      xmldomElem2:= xmlNodeList2.item(0); //mbs:CustomerAuthentication
                      IF NOT ISCLEAR(xmldomElem2) THEN
                      IF xmldomElem2.hasChildNodes() THEN
                         BEGIN
                         xmlNodeList3:= xmldomElem2.childNodes();
                         IF NOT ISCLEAR(xmlNodeList3) THEN
                          xmldomElem3:= xmldomElem2.firstChild();//mbs:No
                         IF NOT ISCLEAR(xmldomElem3) THEN
                          txtNo:=xmldomElem3.text();
                         xmldomElem3:=xmlNodeList3.item(1); //mbsName
                         IF NOT ISCLEAR(xmldomElem3) THEN
                          txtName:=xmldomElem3.text();

                      xmldomElem2:= xmlNodeList2.item(1); //mbs:CustomerData
                      IF NOT ISCLEAR(xmldomElem2) THEN
                      IF xmldomElem2.hasChildNodes() THEN
                         BEGIN
                         xmlNodeList3:= xmldomElem2.childNodes();
                         IF NOT ISCLEAR(xmlNodeList3) THEN
                          xmldomElem3:= xmldomElem2.firstChild();//mbs:Balance
                         IF NOT ISCLEAR(xmldomElem3) THEN
                          txtBalance:=xmldomElem3.text();
                         xmldomElem3:=xmlNodeList3.item(1); //mbsSalesPersonCode
                         IF NOT ISCLEAR(xmldomElem3) THEN
                          txtSPcode:=xmldomElem3.text();
                         END;

                         xmldomElem3:=xmlNodeList3.item(2); //mbs:Contacts
                         IF NOT ISCLEAR(xmldomElem3) THEN
                            txtContact:=xmldomElem3.text();

                     END;
                END;
                      MESSAGE('This is record "%1"\No "%2"\Name "%3"\Contact "%4"\Balance "%5"\Salesperson code "%6"\of Total "%7"',
                      FORMAT(i+1),
                      txtNo,
                      txtName,
                      txtContact,
                      txtBalance,
                      txtSPcode,
                      ii);

                END;
                ffile.CLOSE;
                CLEARALL;
              END;

      }
      CODE
      {
        VAR
          xmldomDoc@1000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v6.0'.DOMDocument";
          xmlNodeList1@1005 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF82-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMNodeList";
          xmlNodeList2@1017 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF82-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMNodeList";
          xmlNodeList3@1019 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF82-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMNodeList";
          xmldomElem1@1007 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF86-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMElement";
          xmldomElem2@1010 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF86-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMElement";
          xmldomElem3@1011 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 6.0:{2933BF86-7B36-11D2-B20E-00C04F983E60}:'Microsoft XML, v6.0'.IXMLDOMElement";
          txtNo@1001 : Text[30];
          txtName@1002 : Text[30];
          txtContact@1009 : Text[30];
          txtBalance@1012 : Text[30];
          txtSPcode@1013 : Text[30];
          ffile@1003 : File;
          strInStream@1004 : InStream;
          i@1006 : Integer;
          ii@1018 : Integer;

        EVENT xmldomDoc@1000::ondataavailable@198();
        BEGIN
        END;

        EVENT xmldomDoc@1000::onreadystatechange@-609();
        BEGIN
        END;

        BEGIN
        END.
      }
    }

    That's all
    Special thanks to
    Rainer Kuhnlein

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

     

  • Microsoft Dynamics NAV Team Blog

    Microsoft Dynamics NAV and SQL Server Database Compression

    • 9 Comments

    Microsoft SQL Server 2008 introduces two new compression features (available in Enterprise Edition) that are of interest to users with large databases. Data compression applies to individual tables and indexes within a database and comes in two options: ROW and PAGE. Backup compression is a new option when backing up a database to external storage. Both compression techniques can be used to reduce the amount of online storage required for databases. Data compression can be configured for an entire heap (table with no clustered index), clustered index, non-clustered index, or indexed view. For partitioned tables and indexes, the compression option can be configured separately (and differently) for each partition. Compression can also reduce disk utilization and sql memory utilization as dead is stores on disk in a compressed state and also reads in the SQL cache in a compressed state. Compression can add 10 - 30% percent increased CPU utilization depending on what tables and indexes are compressed and what level of compression is used.

    For Dynamics NAV we recommend only compressing tables and indexes that have a read to write ration of 80%/20% (This is a conservative threshold) or higher as compressing tables with a higher write ratio can actually decrease performance. We also recommend using ROW compression if the space saving between ROW and PAGE level compression is less that 10%; if the difference is over 10% then we recommend PAGE compression. This is because if the space savings from PAGE compression is close to or similar to ROW compression then it is not recommended to incur the additional overhead associated with PAGE compression. An example of NAV tables that would benefit greatly from compression are the large "Entry" tables such as G/L Entry, Value Entry, and Item Ledger Entry. An example for NAV tables that would not benefit from compression and where performance may actually decrease due to compression are "Line" tables where the data is temporary in nature such as Sales Line, Purchase Line, and Warehouse Activity Line. SQL Server compression is completely transparent to the Dynamics NAV application.

    Compression is done on Table or Index basis. On tables with clustered indexes the clustered index is the table so compressing the clustered index is equal to compressing the table. Running the ALTER TABLE.. WITH COMPRESSION is only necessary on HEAPS for all tables with Clustered Indexes you can use the ALTER INDEX.. WITH COMPRESSION.

    How to determine the read/write ratio of an index? Luckily SQL keeps track of this for us and all we need to do is extract this data. SQL Server stores this information in the sys.dm_db_index_operational_stats DMV. Remember DMV's are "recycled" each time the SQL Server service is restarted so if SQL has only been up and running for a day or a week this information will be of minimal use. Ideally you would want the server to be up any running for several weeks and through a month end close to get a true idea of actual data access patterns of your database.

    The following query will tell you how long the SQL Server instance has been up and running:

    select 'Sql Server Service has been running for about '

           + cast((datediff(hh, create_date, getdate()))/24 as varchar(3)) + ' days and '

           + cast((datediff(hh, create_date, getdate())) % 24 as varchar(2)) + ' hours'

           from sys.databases where name = 'tempdb'

    The following query will give the approximate read write balance of all the used indexes in the database.

    SELECT o.id, 

                            o.name,

                            x.name,

                            i.index_id,

                            x.type_desc,

                            s.rowcnt,

                            i.leaf_update_count * 100.0 /

                                  (i.range_scan_count + i.leaf_insert_count

                                      + i.leaf_delete_count + i.leaf_update_count

                                      + i.leaf_page_merge_count + i.singleton_lookup_count

                                  ) as Writes,

                            i.range_scan_count * 100.0 /

                                  (i.range_scan_count + i.leaf_insert_count

                                      + i.leaf_delete_count + i.leaf_update_count

                                      + i.leaf_page_merge_count + i.singleton_lookup_count

                                  ) as Reads

                  FROM sys.dm_db_index_operational_stats (db_id(), NULL, NULL, NULL) i

                  JOIN sys.sysobjects o ON o.id = i.object_id

                  JOIN sys.indexes x ON x.object_id = i.object_id AND x.index_id =

    i.index_id

                  JOIN sys.sysindexes s ON s.id = x.object_id and s.indid = x.index_id

                  WHERE (i.range_scan_count + i.leaf_insert_count

                            + i.leaf_delete_count + leaf_update_count

                            + i.leaf_page_merge_count + i.singleton_lookup_count) <> 0

                  AND objectproperty(i.object_id,'IsUserTable') = 1

                 

    You can also run a simulation with the sp_estimate_data_compression_savings stored procedure in SQL with will run a sample of the data through the chose compression level and give you the estimate of the space saved by enabling compression.

    I strongly recommend reading the following MSDN article before engaging in database compression activities.

    http://msdn.microsoft.com/en-us/library/cc280449.aspx

    Note: You can use the following query to check to see if there are currently any compressed indexes in the database.

    SELECT o.name Table_Name, p.index_id as Index_ID, i.name as Index_Name,

          CASE

          WHEN p.data_compression = 1 THEN 'ROW Compression'

          WHEN p.data_compression = 2 THEN 'PAGE Compression'

          ELSE 'ERROR'

          END Compression_Type

    FROM sys.partitions p

    JOIN sys.objects o ON p.object_id = o.object_id

    JOIN sys.sysindexes i ON o.object_id = i.id AND p.index_id = i.indid

    AND p.data_compression in (1,2)

    ORDER BY o.name, p.data_compression, p.index_id

     

    Michael De Voe

    Senior Premier Field Engineer

    Microsoft Dynamics

    Microsoft Certified Master - SQL Server 2008

  • Microsoft Dynamics NAV Team Blog

    RDLC Report and Performance in Microsoft Dynamics NAV

    • 9 Comments

    It has been a while since I last blogged and I am taking the chance now to post on a very delicate argument. The main focus of my dissertation is about performance (Out Of Memory exception, typically) with Microsoft Dynamics NAV 2009 R2, Microsoft Dynamics NAV 2013, and Microsoft Dynamics NAV 2013 R2.

    I would encourage you to post your comments and thoughts. Have a good read.

    Microsoft Dynamics NAV 2009 R2 Considerations (RDLC 2005 - Report Viewer 2008)

    All the Microsoft Dynamics NAV 2009 stack (RTM, SP1, R2) is built and sealed for the x86 platform. This means that both client (Microsoft.Dynamics.NAV.Client.exe) and server (Microsoft.Dynamics.NAV.Server.exe) are 32bit components of the NAV platform. RDLC Reporting (Enhanced Reporting, in the recent NAV terminology) in Microsoft Dynamics NAV 2009 is made of a Report Viewer .NET Control targeted for WinForm, and Microsoft Dynamics NAV casts this control into a Microsoft Dynamics NAV modal page (that is a WinForm, roughly speaking) within the RTC boundaries.

    Report Viewer works, in principle, accepting 2 items:

    -          a metadata definition plain XML file (Report.rdlc) that define the structure of the report rendering runtime  

    -          a Dataset that is a serialized XML file that contains the data to be rendered in the way defined in the rdlc file definition

    With Microsoft Dynamics NAV 2009, Report Viewer works client-side to render the report to the user (Preview Layout rendering extension) and therefore it needs to have both RDLC definition and dataset streamed completely from the Server to the Client. This streaming process of Client memory population, since Microsoft Dynamics NAV 2009 SP1, is made with a chunking method that can be resumed in shorts as per below.

    SQL Server process and generate a complete Result Set. The Result Set is sent to the Microsoft Dynamics NAV Server as normal TCP packets informations and the Microsoft Dynamics NAV Server, meanwhile receiving these packets from SQL Server, is sending this Result Set in chunks to the client, clearing the Microsoft Dynamics NAV Server memory once the packet is received from the client. This has been introduced to avoid memory leak server side that works only as routing point for packets / chunks from SQL Server to the Microsoft Dynamics NAV Windows client. If you open task manager both in the Middle Tier machine and Client machine, meanwhile processing a Heavy report (or whatever report), you might notice that the memory footprint server side is constant and pretty low while the Client one is growing and growing in consumption until it reaches a physical limit.

    When it reaches its physical limit, you receive the typical error message like the one shown below (explicit Out Of Memory exception)

    And, most of the times, report viewer continue clearing the error message and simply display a single blank page (implicit Out Of Memory exception) or several pages with mixed random string value assignments (blurred Out of Memory exception).

    I do not want to go more deep into the technicalities that lies beneath but you have to consider the following:

    1. The Microsoft Dynamics NAV 2009 R2 Role Tailored client is a 32bit application (with a limit, on the chart, of 2GB memory per process).
    2. The Microsoft Dynamics NAV 2009 R2 Role Tailored client and report(s) share the same memory Application Domain (this means the same memory stack).
    3. Report Viewer control run in a sort of sandbox mode inside the Microsoft Dynamics NAV WinForm so that the memory consumption is even more limited (approx. 1GB).

    Based on the assumption above my studies on performance related to heavy reports have been the following:

    1. Report Viewer Preview rendering extension within Role Tailored Client is raising an Out Of Memory exception when Client process memory reaches 0.8 – 1.1 GB approx. (this differs between multiple factors like e.g. OS, Hardware type, Resources, etc.)
    2. Considering a typical Microsoft Dynamics NAV dataset (60 – 80 columns on average) there is a potential risk of Out Of Memory between 40K up to 100K rows range. This depends on number of columns in the dataset and quality of columns (e.g. which data type they belongs, if and how this is populated, etc.).

    If you pack up all these considerations, these are the actions that you might take (or have to) depending on your scenarios within the Microsoft Dynamics NAV 2009 R2 stack:

    1. If your report is raising an Out Of Memory exception in a range lower or close to 80/90K rows then you can try to optimize the report by reducing the Dataset. Reducing the dataset means :
      1. Write optimal code for RDLC Report (e.g. use CurrReport.SKIP when needed, avoid use data items for CALCSUMS and use record AL variables instead, rewrite the report to use drill-through to enable getting to details if required in the report - so still possible to move calculations to CSIDE – or refactor to use hyperlink to another report for details, etc.)
      2. Reduce the Dataset Columns (e.g. eliminate Section control that you do not use with RDLC report)
      3. Reduce the Dataset Rows (refactor as much as it possible to push in the dataset only the data that need to be printed)
    2. If your report is already in a range equal or higher then 80/90K then you have no other choices with NAV 2009 R2 than the following :
      1. Delete RDLC Report layout and enable Classic Client report fall back (this is the solution that I will warmly suggest and it is a really finger snap solution)
      2. (this is pretty obvious) Apply filters in the request page (or through AL Code) in order to reduce the amount of rows in the dataset and instead of print the report in one single shot, print it N times.

    And this is all about the Microsoft Dynamics NAV 2009 R2 stack and how to solve / workaround the problem in the feasible (and easiest way) within this version.

    Microsoft Dynamics NAV 2013 (RDLC 2008 – Report Viewer 2010) / NAV 2013 R2 (RDLC 2010 – Report Viewer 2012) is another story and challenge type.

    To resume, the milestone changes between Microsoft Dynamics NAV 2009 and Microsoft Dynamics NAV 2013 (and R2) are the following:

    1. Microsoft Dynamics NAV Server is now 64bit (finally…) while the Windows client still remains as 32bit application. This means that the client is still a physical bottleneck and are still valid the considerations related to memory footprint and dataset volume as reported previously for Microsoft Dynamics NAV 2009 R2.
    2. You cannot anymore enable Classic client report fallback but you have to use RDLC Report in any occasion.

    With these 2 new variables or constraints in mind, below how you could workaround / resolve the performance problem with Microsoft DynamicsNAV 2013  / Microsoft Dynamics NAV 2013 R2:

    1. Same considerations about Optimizing reports: if you receive (or think of receiving) an Out Of Memory exception you might go for optimize the report as much as you can IF you forecast that in the end your dataset will never ever exceed 70/90K rows.
    2. If you have heavy reports with a dataset volume higher than 70/90K rows then this is what you could do:
      1. Filter data and print the report N times, wherever possible (use common sense)
      2. Use the Job Queue to enable Server Side Printing. What is Server Side Printing? It is simply running Report Viewer totally in the background through NAS Services (that is using Background Sessions through STARTSESSION AL statement). Running Server Side means running under 64 bits context and therefore Report Viewer (“.NET component targeted for any CPU” = 64 bit enabled) will use ALL the memory available from the OS (e.g. if you have 32 GB it could reach up to consume all of these if you have to work with several MILLION of dataset rows – I have seen it with my own Italian eyes - ) and you will succeed in PRINT the report or, better, use SAVEASPDF to generate a PDF file to be consumed by the user.
      3. Use STARTSESSION AL statement as you like in your own custom code after gathering user filters and parameter and pass this to a Codeunit that does filter record(s) and run a SAVEASPDF in the background as per your exotic flavor.

    THE FUTURE

    The Microsoft Dynamics NAV Core team is fully aware about these scenarios and working hard on improving the RDLC Report performance and experience in future versions of Microsoft Dynamics NAV

    NOTE:

    In this blog post you will find a set of objects (1 Report, 1 Codeunit, 1 Page) to easily simulate an Out Of Memory exception or Save as PDF the report in background.

    Just import these NAV object set and run Page 50666. You can choose to simulate an Out Of Memory exception by clicking the appropriate Action and then Preview the Report or you can choose to SAVEASPDF the same Report via enabling a Background Session that would do this action Server Side. 

    Be sure to have at least 4 GB of Available Memory Server Side and just wait for the background session to end its activity and stream out the content of the report (this should take close to 5/6 minutes with a standard Cronus database, depending on resources).

    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 Peter Borring Sørensen & Torben Wind Meyhoff from the Microsoft Dynamics NAV core team.

  • Microsoft Dynamics NAV Team Blog

    Microsoft Dynamics NAV 2013 R2 available in the Windows Azure Portal under MSDN subscription

    • 9 Comments

    Ever wondered what it is like to work with Microsoft Dynamics NAV on Windows Azure - but found it too cumbersome even with our nice Windows Azure provisioning tools?  Then this might be something for you. 

    Today we have made Microsoft Dynamics NAV 2013 R2 easily available on Windows Azure with just a few clicks. The Microsoft Dynamics NAV 2013 R2 image is an exclusive offer for MSDN subscribers and includes a fully functional, ready to use Microsoft Dynamics NAV 2013 R2 installation including Microsoft SQL Server. The MSDN subscription gives you the well-known discounted prices and allows you to use it for development, test, and demo purposes, but not for production purposes.

    How to get it? Make sure you have an MSDN subscription and the subscription has Windows Azure benefits activated. Then follow these steps:

     

    1. Sign in to the Windows Azure Portal using your MSDN subscription.
    2. Choose the + sign at the bottom of the Portal page.
    3. Choose Compute, point to Virtual Machine, and then choose From Gallery.
    4. Select the MSDN filtering checkbox as shown in the following screenshot. This will filter the list to only show the available MSDN images.

    1. Choose the Microsoft Dynamics NAV 2013 R2 image.
    2. Choose the arrow in the lower-right corner.
    3. Fill in the relevant fields about the virtual machine as described in the following list:
      1. Specify the name of the virtual machine.
      2. Specify the size of the virtual machine, such as Medium.
      3. Specify the user name and password for connecting to the virtual machine.
      4. Specify the region  where you want to host your virtual machine, such as West Europe.
      5. Verify the remaining parameters. In most cases, the default values are sufficient.
    4. Choose the Finish icon to start the provisioning process.
    5. Once the image is provisioned after a few minutes, you can use Remote Desktop to connect to it. In the Azure Portal Virtual Machine page, choose the newly created image, and then choose Connect. Use the credentials that you specified step 7.

    When you are connected to the VM, you are welcomed to the Microsoft Dynamics NAV 2013 R2 virtual machine on Windows Azure:

    No further configuration is required and you can immediately start using the clients and the development environment.

    Best regards

    Kamil Koclega & Morten Jensen from the Dynamics NAV team

  • Microsoft Dynamics NAV Team Blog

    Update Rollup 4 for Microsoft Dynamics NAV 2013 R2 has been released

    • 9 Comments

    Update rollup 4 includes all application and platform hotfixes and regulatory features that have been released for Microsoft Dynamics NAV 2013 R2 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
    • SE - Sweden
    • UK - United Kingdom

     

    New in update rollup 4 

    Beginning with update rollup 4, the update rollups for Microsoft Dynamics NAV 2013 R2 now also includes hotfixes for the upgrade toolkit. 

     

    Where to find update rollup 4

    You can download update rollup 4 from KB 2930617 - Update Rollup 4 for Microsoft Dynamics NAV 2013 R2 (Build 36078).

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

    CustomerSource:

    PartnerSource

     

    More Information

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

  • Microsoft Dynamics NAV Team Blog

    Memory usage in Microsoft Dynamics NAV 2013 print preview

    • 9 Comments

    Periodically we receive requests where customers asking us about RTC print preview consumes all available memory and computers hangs.

    Repro scenarios are more/less similar: run report, click preview, go per pages up/down, close report. Run another report, click preview, go per pages up down and… RTC hangs.
    If we look to memory usage, NAV is using all available memory.

    If we analyze what has happened, we see: with every move per pages memory usage increase and increase and increase until all memory is used.
    It looks like typical memory leak because in NAV 2009 with the same repro everything is OK.

    However it is not so simple. What NAV does in this scenario is: it loads Microsoft Report Viewer 2010 with 2 files: report definition (RDL file where is described report structure) and record set. And that is all, next actions like preview/print/export are managed by report viewer. The same we have in NAV 2009 just it loads Report Viewer 2008 and .NET Framework 3.5 as NAV 2013 uses Report Viewer 2010 and .NET Framework 4.5. And here is reason pointing us to memory usage behavior: Report Viewer 2010 and .NET 4.5 uses another way to manage memory (named more advanced and more secure). However this ‘another’ way gets us mentioned questions from customers and really we can do nothing from NAV platform side – system works as it is designed to work.

    But things are not so bad. In .NET memory is managed very smart and not used memory is released by function named ‘garbage collector’. This function periodically review memory blocks and release not used. And actually it works: if we monitor memory during report previewing and after it close we see that in preview and going per pages memory usage increase, after preview close memory usage is still the same, but after 5-10 min used memory decrease to initial numbers. For example in my tests started RTC using 98.5 MB, after few previews and scrolls and etc. usage increases to 215 MB and doesn’t decrease if I close preview. But after few minutes garbage collector returns usage to 100.4 MB.
    We can force (in NAV platform) garbage collector to work faster and memory release will be faster, but this will increase processor usage and in many cases it is worse than memory usage.

    Few trick could help users do not meet memory problems:

    1. When we open report preview we see report in “funny” interactive mode. This is preview mode where we can change report view in some way described in report code. For example in report ‘Customer – Top 10 List’ sorting can be changed. But exactly this mode is memory monster. If we click ‘Print layout’ button in menu we come to ‘page view’ where we can change nothing in report and see exactly what will be printed. This mode doesn’t use memory so much, so we can use this view easier. Few additional points here: a) all report initially open in interactive mode so users need manually change mode; b) Mode is not available if report is not allowed to preview like Sales Invoice or Order Confirmation.
    2. Report run SAVEASPDF works better if we call it directly without request form. However then users need to do more actions to open report. But maybe this can be reasonable in some cases.
    3. And finally if there are requirements to run big reports with many pages (100 and more) then better is to run them on server side, just because server is 64 bits and usually has more available RAM. This can be done by creating codeunit which runs report SAVEASPDF. Then add codeunit to job queue. Job queue executes codeunit and create pdf file.

     

    New Information since Update Rollup 5:

     

     

     

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

     

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

     

  • Microsoft Dynamics NAV Team Blog

    How to Deploy a Microsoft Dynamics NAV 2013 R2 Help Server

    • 8 Comments

    As most of you have already found out, we, the NAV R&D team, have developed a new Help Server that shows Help on a website. Help is available for the Windows client as in earlier versions. With the Help Server, the same Help is available from the Web client. Choose a field, and context-sensitive Help opens.

    The Help Server is a website that displays HTML files. Yes, you read correctly: HTML files. So you don’t have to decompile the Microsoft CHM files anymore. But the really good news is that the Help that you created for your current NAV solution will still work with the new Help Server. You just need to build it again with the new Help Toolkit, and then copy the resulting HTML files to the relevant folder on the Help Server website. Then, you can start connecting your users to the Help Server.

    Here are the main steps for deploying your Help to your customers.

    1. Install the Microsoft Dynamics NAV 2013 R2 Help Server. For more information, see Microsoft Dynamics NAV Help Server in the MSDN Library.
      • When you choose the Help Server option in Microsoft Dynamics NAV Setup, a Help Server website is set up for you with folders containing the HTML Help that Microsoft provides.
    2. Install the Microsoft Dynamics NAV 2013 Help Toolkit that is available for download from PartnerSource.
    3. Rebuild your existing Help files with the NAV 203 version of HelpBuilder, but change some of the configuration settings. For more information, see Upgrading Your Existing Help Content in the MSDN Library.

    4. Add the HTML files that HelpBuilder creates to the relevant language-specific folders on your Help Server website.

    5. Grant your users access to the website.

    6. Configure the Microsoft Dynamics NAV 2013 R2 clients to look up Help on your Help Server.

      • This configuration is part of Microsoft Dynamics NAV 2013 R2 Setup. Alternatively, you can configure the Web client server components and the Windows clients manually.

    7. Start a Microsoft Dynamics NAV 2013 R2 client and access Help.

    You can set up a Help Server that all your users can access, or you can set up multiple Help Servers. You can modify the Microsoft-provided Help content without decompiling anything, and you can add and remove Help content whenever you want to. You can add links to existing Word documents or PDF documents to the navigation pane of the Help Server website, so that you users have a single point of entry for Help.

    With the Microsoft Dynamics NAV 2013 R2 Help Server, you can provide the Help content that is relevant for your users, and you can update Help without modifying each client computer.

    We will improve the Help Server in future releases of Microsoft Dynamics NAV, so we hope you will like it as much as we do.

     

    Best regards,

    The Dynamics NAV team

Page 3 of 43 (645 items) 12345»