Using Web Services to Access Microsoft Dynamics NAV 5.0


Introduction


Dynamics NAV 2009 contains a new subsystem for dealing with Web Services. This feature has been well received by partners and customers alike. Partners have expressed interest in having web services available for earlier versions of Dynamics NAV. This feedback resulted in a technology talk at Directions2007 in Florida, where the topic was what could be done to day. The conclusion of the talk was that everything we where intending to deliver was already possible today, yes some code is needed but strictly from function/feature perspective all of it is possible, and it is not even all that ugly. Dynamics NAV 2009 will provide out-of-the-box programmatic web service access to the application and will therefore remove the need for this additional technology plumbing described here.

I have to say that the response to my talk has been tremendous. After the response to my talk on Web Services in NAV 5.0 and previous versions I decided to write this blog post and make the source files available.

This post is about how to bridge the gap between the need for web services now and the current platform, it will help you understand how you can provide Web Services directly from Dynamics NAV today, in a “simple” and flexible way, already today.

To work with the samples in this post you will need: Visual Studio 2005, Dynamics NAV 5.0 and .Net 3.0 installed on your system. This sample should work on Dynamics NAV 4.0 to but has not been tested on that version.

Architecture


The system we will build contains 4 different components/moving parts: Web Service Listener, Event Dispatcher, Codeunit Eventhandler and XMLPort for stream handling.

image

Web Service Consumer


Any client that understands how to communicate with Web Services; like InfoPath, Visual Studio, SharePoint or any custom application written by you.

Port


Is the physical communication port that the WCF listens to.

WCF Web Service


Defines the data contracts and service contracts for the Web Service, it also implements the concrete service and opens for listening in the WCF subsystem, it then delegates the requests to the COM Event Dispatcher component.

COM Event Dispatcher


This component provides the hookups for Dynamics NAV, both to activate the service and to register event sinks. It defines 2 IDispatch interfaces the IServiceEvents and the IWebServiceListner, as well as the concrete implementation of the IWebServiceListner in the WebServiceListner class that provides the actual code for hooking up the WCF Web Service to Dynamics NAV.

.NET


We are using the CLR runtime for writing our Web Service component and our COM plugin. Some of this blog entry is about interop between Dynamics NAV and .NET through COM.

Codeunit Event Handler


Is responsible for starting up the WCF Web Service through the COM interface, it then registered for events coming from the WCF Web Service Component. The events routed to XMLPort for processing.

XMLPorts for datastreams


It deals with the actual business logic and data coming from or going to the Web Service.

Implementation


The implementation is in 2 programming languages: C# and C/AL.

Please take a look at the provided code sample, for the rest of the information contained in the posting. It can be found here: http://code.msdn.microsoft.com/nav/Release/ProjectReleases.aspx?ReleaseId=896

I have included comments in the code that should explain what is going on, if you feel something is missing, first look at the documentation for the WCF or post a comment to this post and I will try to answer it.


Deployment of Sample


To deploy the sample you will first have to download it, unpack it.

Then open it up with Visual Studio and compile.

Then import the codeunit.txt and xmlport.txt into your NAV installation and compile those objects, starting with the XMLPort

To run the service simply open the Object Designer in NAV, find the Codeunit that you just imported and press run.

There is no dependency on IIS or other external components. No further deployment steps should be needed.

In the Visual studio solution is a ConsoleTestApp project. After you have followed the steps above you can run that project, it will test if your install was successful, as well as provide sample on how to use the web service.

Special considerations


In this sample I’m using XMLPort to handle the XML stream that is provided.

You can take many different approaches to this, and still reuse large please of the code provided in the sample.

To use the XMLPort as handler you will have to set the encoding property to UTF-8. This is due to a null termination bug in stream handler in NAV.

image

image

With this approach you can already today, incorporate web services in your projects in straightforward way.

The appropriate usage is whenever you need to give external application access to Dynamics NAV data or business process.


For any questions or comments please feel free to ask them in the comment section of this blog post.  I will answer questions to best of my ability on this post in the comments section as well.


One last thing:  This is a sample code.  It has not been tested, you should thoroughly test this code before usage.


Best regards,
Kris Rafnsson

Comments (50)

  1. jmadsen says:

    Great article demonstrating a minimal framework for exposing NAV business logic. Seems a little more elegant than MSMQ & easier to deploy.

    I got this to work on NAV50, but when I try it on NAV50SP1 I receive this error: "The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT))". This error is reported by the Console App when any method is called on Customer_Service.

    It seems to me to be related to Stream/IStream/NAV InStream/NAV OutStream compatibilty or something. Is the InStream/OutStream different in NAV50SP1?

    Thanks for any help,

    Jakob Madsen

  2. "To use the XMLPort as handler you will have to set the encoding property to UTF-8. This is due to a null termination bug in stream handler in NAV. "

    Has this been fixed in NAV5.0 SP1? I have earlier had issues about importing streams into BLOB’s from .NET, but i need to try and test this on SP1.

    Great post about the Webservice. Keep up the good work.

  3. Kenneth Fuglsang says:

    I can’t get it to work on 5.0SP1 either but 5.0 works.

    Ikke-afviklet undtagelse: System.Web.Services.Protocols.SoapHeadeHeaderException: Serveren kunne ikke behandle anmodningen på grund af en intern fejl. (the server could not execute the request because of an internal error).

      ved System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapCli

    entMessage message, WebResponse response, Stream responseStream, Boolean asyncCa

    ll)

      ved System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String method

    Name, Object[] parameters)

      ved ConsoleTestApp.localhost.Customer_Service.Read() i C:UserskfcDesktopS

    ample – WebServicesinNAV5ConsoleTestAppWeb ReferenceslocalhostReference.cs:l

    inje 113

      ved ConsoleTestApp.Program.PrintAllCustomers() i C:UserskfcDesktopSample

    – WebServicesinNAV5ConsoleTestAppProgram.cs:linje 21

      ved ConsoleTestApp.Program.Main(String[] args) i C:UserskfcDesktopSample

    – WebServicesinNAV5ConsoleTestAppProgram.cs:linje 12

  4. Kris Rafnsson says:

    I will look into the issue regarding 5.0 SP1 sometime next week.

    This approach should work on Dynamics NAV 4.0 as well.

  5. Ravinder Pal Singh says:

    cool.

    When I import the dataport, i get the error

    "There is a syntax error in the import on line 33 in position 2 : REQUESTPAGE.

    A’}'(ListEnd) is expected here.

  6. bleisibach says:

    Ravinder. I just removed the Code-Part REQUESTPAGE including PROPERTIES and CONTROLS and was able to import then without Problem.

    Kris. Tnx for the Posting. Works fine here on 5.0-CH.

  7. Andrzej says:

    To make it work with all Nav versions, you have to change 2 lines in Stream.Write method:

    line:

    Marshal.WriteInt64(pcbWritten, (long)cb);

    change to:

    Marshal.WriteInt32(pcbWritten, cb);

    and line:

    Marshal.WriteInt64(pcbWritten, (long)0);

    change to:

    Marshal.WriteInt32(pcbWritten, 0);

  8. Jonas says:

    Thanks for a great example!

    I have a couple of questions:

    1) Are there any problems if multiple clients makes calls at the same time? Are there any queue handling?

    2) Error handling in NAV. If there’s an error in NAV, can I get that error back to the client?

  9. Kenneth Fuglsang says:

    I just tried this on another computer with Windows Server 2003 and Dynamics NAV 5.0SP1.

    The compuiter has .net 2.0, 3.0 and 3.5. I registered the dll like so:

    C:WINDOWSMicrosoft.NETFrameworkv2.0.50727>RegAsm.exe c:NAVWebServiceDemobinDebugNAVWebServiceDemo.dll /tlb:c:navwebservicedemobindebugNAVWebServiceDemo.tlb

    Yet, when I try to start the codeunit I get this error:

    It was not possible to create an instance of the OLE-object… etc.

    However, I can compile the codeunit with no problem.

    I noticed that the Input and Output functions is of type IUNKNOWN inside NAV.

    Any ideas?

  10. Kris Rafnsson says:

    Jonas:

    The code should serialize calls to NAV.

    However for large number of requests you should do something different.

    Errors should be propagated when you run this on the NAS.

    Kenneth:

    Try to run the RegAsm with /verbose flag set and see if you can get better info over the registration.

  11. Kenneth Fuglsang says:

    Kris:

    I’m afraid it doesn’t give a lot of helpful information.

    C:WINDOWSMicrosoft.NETFrameworkv2.0.50727>regasm c:_SharedNAVWebServiceNA

    VWebServiceDemobinDebugNAVWebServiceDemo.dll /tlb c:_SharedNAVWebServiceNAVWebServiceDemobinDebugNAVWebServiceDemo.tlb /verbose

    Microsoft (R) .NET Framework Assembly Registration Utility 2.0.50727.1433

    Copyright (C) Microsoft Corporation 1998-2004.  All rights reserved.

    Types registered successfully

    Type ‘N’ exported.

    Type ‘N’ exported.

    Type ‘N’ exported.

    Assembly exported to ‘c:_SharedNAVWebServiceNAVWebServiceDemobinDebugNAVWebServiceDemo.tlb’, and the type library was registered successfully

  12. Kenneth Fuglsang says:

    Just found the solution.

    When registering with RegAsm you need to use the /codebase parameter.

    This should only be used for signed assemblies, so I’ll have to reregister it in a bit.

  13. Marcel says:

    Hi, i’m not so familar with Visual Studio, so please tell me step by step how to compile the VS Files and register it for use with NAV. I have installed Visual C# Express 2008 and MS .NET Framework SDK 2.0 on my PC. Thank in advance for your help. Best regards Marcel

  14. Kris Rafnsson says:

    Andrzej:

    I have not had the time to look at you fix to my code you did.  However this fix makes sense.  And thank you for it.  As the complains for SP1 compatibility don’t show up any more I assume it is what it takes to get this working with SP1.  

    Marcel:

    Make sure that you do the changes that Andrzej suggested.  I have not tried myself with express version of Visual Studio, but if it compiles without errors and warnings,  it should run.  

    That means that you should be able to load the project file.  

    Compile

    Import the objects

    Compile the NAV objects

    And run

    Thanks

    Kris

  15. AG says:

    Has anybody tested it on 4.0.3 ?

  16. salman says:

    how does the code unit stop running the service.

  17. Bruno Pereira says:

    How can I have the client on a different machine (instead of localhost) and still have this working?

    We have to build another layer to comunicate with the outside, right? And then we’ll need IIS…

    Or am I wrong?

  18. vlieffroy says:

    Hello,

    nice to see that NAV could be Web services enabled theorically.

    But what are exactly the business processes that could accessed from outside. I mean i think it is quite easy to enable access to the data of the ERP from outside. But how  could an external client access some of the business processes via a web services ? How is the data integrity and the business processes accessed ? When one needs to create an order entry or a customer invoice from outside of the ERP, how could the web service replace the business logic of the traditional GUI ?

  19. Kris Rafnsson says:

    AG.

    I did test on some version of 4.x at point in time, not sure what version exactly.  You should try, most likely it will work.

    salman:

    You will have to add new method to the COM object that allows for stopping.  Then call this method from within NAV, if you need to call it from outside NAV, you could expose that as a Web Service through the same infrastructure 🙂

    Bruno Pereira:

    I have not tested but this should work already from different box.  

    You need to use the actual computer name of the PC that is running the web service in steed of the localhost, in your consumer.  

    Make sure your firewalls are not stopping the traffic.

    There is no need for IIS.

    vlieffroy

    I think that we see differently on this issue.  

    First I don’t consider the GUI, business logic, but a way to access it.  And as such it has been coded to fit a special actor, flesh and blood user.  I look at Web Services as just another way for accessing this business logic, and it too needs to be coded to fit the actors that should use it, those actors are usually other computer systems.

    I don’t have that as a goal to replace GUI with web services but just to compliment the application in this case NAV with access to the data and processes for other systems.

    As for the rest of the questions,  this sample does not address that directly, this is more of a plumbing for building your own answer to those questions.  Microsoft Dynamics NAV 2009 will however provide some application level implementation that answers those questions.   I will write more about that later.

    Thanks

    Kris Rafnsson

  20. Kris,

    Yes, we definitely see different. I agree with you on the fact that Web Services do not replace the GUI.

    But (this is the point) how could the business logic be ‘translated’ in Web Services : how could an Order-to-Cash process be used with Web Services, in place of GUI. This is why i menton business logic. This is the critical issue with SOA.

  21. Kris Rafnsson says:

    Sorry for the late reply.

    Nobody wants to wait for Dynamics NAV 2009 longer than absolutely needed.  I´m pulling my share of the load 🙂

    Thanks for constructive debate vlieffroy@lecxp.com,  it is much appreciated.

    There are many schools of SOA.  I’m not sure if I have been to any of them yet, so I’m not going to list out answer to your question in SOA terms.

    My understanding of your question is that it is more philosophical, than I feel that my little code sample merits.

    Therefore I’m going to abstract, away from the sample, that is mostly focused on the nitty-gritty details of getting messages in and out of Dynamics NAV, into something completely different.

    Applications like Dynamics NAV have a legacy, which does not fit the idealistic world of modeling software as processes.  Don’t get me wrong, Dynamics NAV is fully capable to manage the order to cash process that you where referring to, and some of us it think it is the greatest thing since sliced bread, but it has legacy.  With legacy come a lot of good things.  Such as proven approach, stable codebase and lot of features.

    Dynamics NAV is architecturally centered around:  Forms (for data entry), Tables (for data storage) and Report (for aggregation and printing of the data), at least from abstraction point of view.  This makes the application task oriented, from the perspective of user that is now going to type in the orders that have just arrived, or print out the invoices needed to be sent out.  

    This architecture is based on even more legacy system that probably dates back hundreds of years.  And therefore more proven, is more stable and has more features.  That is the document/form in triplets (or more).   One could think that the IRS or US immigration had invented the concept just by the share volume of forms they use, but it is not so, they us it simply to the reason of: more proven, stable codebase and lot of features.  

    The funny thing with form in triplet is that at its heart it is message oriented structure.  Depends on the business the copies go to different departments.  Those where processed differently for different departments.

    Web services are also message oriented.  This leaves us with message oriented forms, which is the architectural construct of Dynamics NAV and web services that both are message oriented.

    So far we have established that Dynamics NAV is capable of running the order to cash process (I stated that), it works in task oriented way where forms have center stage and forms are message oriented.  

    How can we make this help us running the order to cash process through web services?

    If we examine this process, it at first appearance looks concrete, there are however as many processes as there are deals made in the world.  Only by very abstract approximation you can claim that there is one process.  There are however general touch points in the process where interaction between customer and vendor frequently happen.  

    If we limit us to very general incarnation of the order to cash process those touch points include but are not limited to: The order, the order confirmation, the shipment notice, the invoice, the delivery and the payment.

    I will try to list the general steps on how you could fulfill those steps from Dynamics NAV perspective in this very limited process:

    The order

    The order is sent through a web service request.  It is filled into the system; a sales person looks at the order and approves it by processing it.

    The system sends order confirmation to the customer with expected delivery dates, as well as notifying the warehouse of the order.  

    Warehouse pushes the ship button when the goods leave the building sending a shipping notice to the buyer and message to the invoicing department.  

    Invoice department sends invoice to buyer.

    Product is delivered.

    Buyer pays at bank.

    Invoice department consolidates with the bank.

    Standard Dynamics NAV has many of those features already build in.  The rest is easy to get partners to add, with the help of the code I have added in this blog.  

    I hope this helps you understand how Web Services can help businesses in the future.  If not please be more specific, and I might be able to answer 🙂

    Thanks

    Kris

  22. Christian says:

    Hi

    I now tested your code with Visual Studio Express 2008 (c#).

    Unluckily I can’t resolve the IUNKNOWN issue.

    Could anyone give me some hints to solve this.

    I tried the /codebase option, but still no progress.

    Thanks in advance!

    //Christian

  23. @ Kris Rafnsson.

    Thanks for the answer. We are quite agree on the purpose and the benefits Web Services could help businesses.

    And this is a short-term journey (hopefully).

    The SOA way on the other hand is long term journey i think (definition and re-definition of business processes by business analysts, without coding anymore etc..).

    Regards,

    Vincent Lieffroy

  24. Kjell H says:

    Hi!

    I’ve just tried to use this sample but I can’t import the xmlport.txt or the codeunit.txt. The message I get is that I don’t have permission to create the xmlport or the codeunit. I do have a developer license for NAV 5.0 and I’m familiar with VS 2008 and .NET since 7 year. I’m rather new to this with NAV and I could use som help to get this running. My version of NAV 5.0 is in Swedish, but I can’t see that this should matter.

    If someone of you guys could provide me with some more information how to get this running I will be most grateful.

    /Kjell H

  25. Kjell H says:

    Hi!

    Back again on the same day as previous post. I finally got the xmlport and codeunit to run. But how do I do to register the webservice ‘localhost’ to the console application? The article says I don’t need to use the IIS but how does this work??

    /Kjell H

  26. Ram says:

    Hi,

    I am trying to use this sample but I can’t import the xmlport.txt or the codeunit.txt.

    I am getting error message  as

    —————————

    Microsoft Dynamics NAV

    —————————

    ‘E:Microsoft NavisionSample – WebServicesinNAV5NAVWebServiceDemoxmlport.txt’ is not a valid Language Module file.

    Any clue on this?

  27. Kjell H says:

    I’ve tried to use this code from both VS 2005 and VS 2008 but I really can’t find any WCF service in the code. Am I missing something or should this be something I have to create to get this to work?

    /Kjell H

  28. Manav says:

    Is it possible to change font size in NAV 5.0 for sales documents like Sales quote,Proforma etc..

  29. Robin says:

    Hi, thanks for your sample code.

    I tried it in Nav 5.0 SP1. That strange thing is that when I try to read Input instream with ReadText(buffer, n). Only the first character can be read. For example, if the input stream is "Hello", only "H" can be read. If I set ReadText(Input, 2). The Nav shows read error. Also I can not read by Read.

    Does anybody have any idea? Thanks

  30. Nishikant says:

    I have gone through all the guid line  given in this blog to start Web Services to Access Microsoft Dynamics NAV 5.0

    with wss3.0 and also downloaded the code sample given in this blog, but I am not able to start Windows SharePoint services 3 Search in Computer Management, Can any one help me for this problem?

  31. mahir says:

    hi, I can not find that Automation that you are using? what is it called? and is it something that is in the windows server (+ .NET 3) ??

    thx in advance..

  32. Kris Rafnsson says:

    Robin:  did you try following?

    Andrzej said on April 19, 2008 10:31 AM:

    To make it work with all Nav versions, you have to change 2 lines in Stream.Write method:

    line:

    Marshal.WriteInt64(pcbWritten, (long)cb);

    change to:

    Marshal.WriteInt32(pcbWritten, cb);

    and line:

    Marshal.WriteInt64(pcbWritten, (long)0);

    change to:

    Marshal.WriteInt32(pcbWritten, 0);

    If that does not help make sure that you are using UTF-8 in all places also in the xmlport.  There is a bug in the NAV internal stream function, it can only work with UTF8

  33. Kris Rafnsson says:

    mahir:

    The automation is called: NAVWebServiceDemo’.WebServiceListner

    You will need to build the project with Visual Studio before it will show up in your list.  

    After the build it should be avalable on Windows server as well as XP and Vista

  34. Kris Rafnsson says:

    Nishikant:  

    There should not be any conflict with wss3.0.

    the project is not using it at all.  

    you can try to change the port number of the WCF service in the project

  35. Nishikant says:

    Kris Rafnsson:

    Can you please brief me how can I use Windows Sharepoint Services 3.0  to call NAV5.0 CodeUnits object? Can you suggest me code example or any blog or even any helping URL for the same? Thanks a lot in advance

  36. Kris Rafnsson says:

    I’m not aware of any blog or code examples that use the WSS together with NAV.  

    Although I have not tried, you should be able to modify this sample to work with the WSS.

    Consider following:  the sample code is not running with in the IIS.  It is using a WCF service hosted within NAV process.  You will have to use a web service to communicate from the WSS to the NAV process.  

    Consider following approach.

    1.) Get the sample up and running.  

    2.) Build a simple web service in Visual Studio that serves some data, as a standalone process (not hosted in IIS)

    3.) Bind that newly build web service to WSS and make sure that it can retrieve the data from that service.

    4.) Take the learning’s from this and refractor the sample in this post to fit your purpose, then link it to WSS.

    5.) Write a blog about the experience and become famous.

  37. Nishikant says:

    Hi Kris,

    Thanks for your reply and the approach you have suggested.

    Let me walk though what you have suggested, You want to say first I need to create web user interface using WSS3.0 and  bind  the web service that I have created using Visual Studio  to WSS3.0, which will call NAV5.0, Is that you mean to say?  Simply you mean to say is  I will have to create web service to call WSS which will call  NAV functionality from WSS user interface. But Kris this WSS site will be hosted on IIS then what? Although the simple web service built by using visual studio could be standalone no doubt about it! Still it is not going to solve this issue?

    What I have done right now I have created one CodeUnit object with XMLport and deployed it into NAV application and trying to call this codeunit object for the web service that I have built in Visual Studio. But the problem is my NAV server is not responding to the MSMQ. I guess it might because authentication functionality provided to server or please let  me know if you may have experience the same?  

    Code Unit code:

    OBJECT Codeunit 50002 RunNavisionProcess

    {

     OBJECT-PROPERTIES

     {

        Date=22.03.08;

       Time=17:03:44;

       Modified=Yes;

       Version List=;

     }

     PROPERTIES

     {

       SingleInstance=Yes;

       OnRun=BEGIN

               IF ISCLEAR(ComCom) THEN

                 IF NOT CREATE(ComCom) THEN

                   ERROR(Text001);

               IF ISCLEAR(MSMQ_BA) THEN

                 IF NOT CREATE(MSMQ_BA) THEN

                   ERROR(Text001);

               ComCom.AddBusAdapter(MSMQ_BA,1);

               MSMQ_BA.OpenReceiveQueue(‘.private$’ + COMPANYNAME + ‘ 1’,0,0);

               MSMQ_BA.OpenReplyQueue(‘.private$’ + COMPANYNAME + ‘ 2’,0,0);

             END;

     }

     CODE

     {

       VAR

         ComCom@1450001 : Automation "{F9A57667-8AC5-45C5-9416-99D3955BCAC0} 1.0:{01018FA5-E4B4-413C-A47C-AD34B0CC2647}:’Navision Communication Component version 2′.CommunicationComponent" WITHEVENTS;

         MSMQ_BA@1450000 : Automation "{B8BD635A-E191-47EF-84A0-02921E2A44A6} 1.0:{CD49794B-0E84-4A2E-9522-C518C825D390}:’Navision MS-Message Queue Bus Adapter’.MSMQBusAdapter";

         Text001@1450003 : TextConst ‘ENU=Cannot create communication components.’;

         Text002@1450002 : TextConst ‘ENU=Document No. cannot be found’;

         Text003@1450004 : TextConst ‘ENU=Document Type is missing in ParameterList’;

         Text004@1450005 : TextConst ‘ENU=Company does not exist’;

         Text005@1450006 : TextConst ‘ENU=Item No. cannot be found’;

         Text006@1450007 : TextConst ‘ENU=Completed’;

         Text007@1450008 : TextConst ‘ENU=Customer No. cannot be found’;

         Text008@1450009 : TextConst ‘ENU=Customer has been blocked in Navision’;

       LOCAL PROCEDURE ReturnOriginalMessage@1240002(OutMsg@1450002 : Automation "{F9A57667-8AC5-45C5-9416-99D3955BCAC0} 1.0:{6CB9762C-E61C-4F96-BA34-8B20D3A5B46E}:’Navision Communication Component version 2′.OutMessage";XMLDoc@1450000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:’Microsoft XML, v3.0′.DOMDocument");

       VAR

         OutStreamQueue@1450001 : OutStream;

       BEGIN

         OutStreamQueue := OutMsg.GetStream();

         XMLDoc.save(OutStreamQueue);

         OutMsg.Send(0);

         CLEAR(OutMsg);

       END;

       LOCAL PROCEDURE SendItem@1450000(ItemNo@1450000 : Code[20];OutMsg@1450006 : Automation "{F9A57667-8AC5-45C5-9416-99D3955BCAC0} 1.0:{6CB9762C-E61C-4F96-BA34-8B20D3A5B46E}:’Navision Communication Component version 2′.OutMessage");

       VAR

         Item@1450003 : Record 27;

         ItemXMLPort@1450002 : XMLport 8002;

         OutStreamQueue@1450004 : OutStream;

         XMLDoc@1450001 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:’Microsoft XML, v3.0′.DOMDocument";

       BEGIN

         OutStreamQueue := OutMsg.GetStream();

         Item.SETRANGE("No.",ItemNo);

         ItemXMLPort.SETTABLEVIEW(Item);

         ItemXMLPort.SETDESTINATION(OutStreamQueue);

         ItemXMLPort.EXPORT;

         CREATE(XMLDoc);

         XMLDoc.save(OutStreamQueue);

         OutMsg.Send(0);

         CLEAR(OutMsg);

       END;

       PROCEDURE PopulateResult@1450001(XMLDoc@1450000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:’Microsoft XML, v3.0′.DOMDocument";Result@1450001 : Text[250]);

       VAR

         XMLNode@1450003 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:’Microsoft XML, v3.0′.IXMLDOMNode";

         XMLDOMMgmt@1450002 : Codeunit 99008516;

       BEGIN

         IF XMLDOMMgmt.FindNode(XMLDoc,’/NavisionObject/Result’,XMLNode) THEN

           XMLNode.text := Result;

       END;

       LOCAL PROCEDURE SendCustomer@1450002(CustomerNo@1450000 : Code[20];OutMsg@1450006 : Automation "{F9A57667-8AC5-45C5-9416-99D3955BCAC0} 1.0:{6CB9762C-E61C-4F96-BA34-8B20D3A5B46E}:’Navision Communication Component version 2′.OutMessage");

       VAR

         Customer@1450003 : Record 18;

         CustomerXMLPort@1450002 : XMLport 50002;

         OutStreamQueue@1450004 : OutStream;

         XMLDoc@1450001 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:’Microsoft XML, v3.0′.DOMDocument";

       BEGIN

         OutStreamQueue := OutMsg.GetStream();

         Customer.SETRANGE("No.",CustomerNo);

         CustomerXMLPort.SETTABLEVIEW(Customer);

         CustomerXMLPort.SETDESTINATION(OutStreamQueue);

         CustomerXMLPort.EXPORT;

         CREATE(XMLDoc);

         XMLDoc.save(OutStreamQueue);

         OutMsg.Send(0);

         CLEAR(OutMsg);

       END;

       LOCAL PROCEDURE FindNode@3(RootNode@1020 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:’Microsoft XML, v3.0′.IXMLDOMNode";NodePath@1000 : Text[250];VAR ReturnedNode@2030 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:’Microsoft XML, v3.0′.IXMLDOMNode") : Boolean;

       BEGIN

         ReturnedNode := RootNode.selectSingleNode(NodePath);

         IF ISCLEAR(ReturnedNode) THEN

           EXIT(FALSE)

         ELSE

           EXIT(TRUE);

       END;

       EVENT ComCom@1450001::MessageReceived@1(VAR InMessage@1450000 : Automation ":{00020400-0000-0000-C000-000000000046}:”.IDISPATCH");

       VAR

         Item@1450012 : Record 27;

         SalesHeader@1450010 : Record 36;

         InMsg@1450003 : Automation "{F9A57667-8AC5-45C5-9416-99D3955BCAC0} 1.0:{D184D0AC-61C9-4AC1-B537-0D28C277FEDE}:’Navision Communication Component version 2′.InMessage";

         XMLDoc@1450006 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:’Microsoft XML, v3.0′.DOMDocument";

         XMLNode@1450005 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{2933BF80-7B36-11D2-B20E-00C04F983E60}:’Microsoft XML, v3.0′.IXMLDOMNode";

         InStreamQueue@1450002 : InStream;

         XMLChar@1450007 : Text[1];

         XMLText@1450004 : Text[1024];

         UserName@1450014 : Text[1024];

         CompanyName@1450013 : Text[1024];

         FunctionName@1450008 : Text[1024];

         ParameterList@1450009 : Text[1024];

         DocumentType@1450011 : Option;

         Company@1450016 : Record 2000000006;

         Customer@1450017 : Record 18;

       BEGIN

         InMsg := InMessage;

         InStreamQueue := InMsg.GetStream();

         REPEAT

           InStreamQueue.READTEXT(XMLChar);

           XMLText := XMLText + XMLChar;

         UNTIL InStreamQueue.EOS;

         CREATE(XMLDoc);

         XMLDoc.loadXML(XMLText);

         IF FindNode(XMLDoc,’/NavisionObject/UserName’,XMLNode) THEN

           UserName := XMLNode.text;

         IF FindNode(XMLDoc,’/NavisionObject/CompanyName’,XMLNode) THEN

           CompanyName := XMLNode.text;

         IF FindNode(XMLDoc,’/NavisionObject/FunctionName’,XMLNode) THEN

           FunctionName := XMLNode.text;

         IF FindNode(XMLDoc,’/NavisionObject/ParameterList’,XMLNode) THEN

           ParameterList := XMLNode.text;

         CASE FunctionName OF

           ‘GetCustomer’:

             BEGIN

               IF Customer.GET(SELECTSTR(1,ParameterList)) THEN

                 SendCustomer(Customer."No.",InMsg.CreateReply)

               ELSE BEGIN

                 PopulateResult(XMLDoc,Text007);

                 ReturnOriginalMessage(InMsg.CreateReply,XMLDoc);

               END;

             END;

           ‘BlockCustomer’:

             BEGIN

               IF Customer.GET(SELECTSTR(1,ParameterList)) THEN BEGIN

                 Customer.VALIDATE(Blocked,Customer.Blocked::All);

                 IF Customer.MODIFY(TRUE) THEN BEGIN

                   PopulateResult(XMLDoc,Text008);

                   ReturnOriginalMessage(InMsg.CreateReply,XMLDoc);

                 END;

               END ELSE BEGIN

                 PopulateResult(XMLDoc,Text007);

                 ReturnOriginalMessage(InMsg.CreateReply,XMLDoc);

               END;

             END;

         END;

         InMsg.CommitMessage;

         CLEAR(InMsg);

       END;

       BEGIN

       END.

     }

    }

  38. Nishikant says:

    XMLPort Code file:

    OBJECT XMLport 50002 Customer

    {

     OBJECT-PROPERTIES

     {

       Date=22.03.08;

       Time=17:05:05;

       Modified=Yes;

       Version List=;

     }

     PROPERTIES

     {

     }

     ELEMENTS

     {

       { [{BF00F684-48BE-4FA3-9A60-D83313729921}];  ;Customer            ;Element ;Table   ;

                                                     VariableName=Customer;

                                                     SourceTable=Table18;

                                                     MaxOccurs=Once }

       { [{36E410F8-09CA-432C-A2D7-9EEB24513092}];1 ;No                  ;Element ;Field   ;

                                                     DataType=Code;

                                                     SourceField=Customer::No. }

       { [{449E6B20-B2AE-4585-BF5D-547100835006}];1 ;Name                ;Element ;Field   ;

                                                     DataType=Text;

                                                     SourceField=Customer::Name }

       { [{0C886C80-C7A9-4E81-AE78-81DE61832033}];1 ;Address             ;Element ;Field   ;

                                                     DataType=Text;

                                                     SourceField=Customer::Address }

       { [{1B4BBDE2-33BA-45B4-93E4-C8E008C45874}];1 ;Address2            ;Element ;Field   ;

                                                     DataType=Text;

                                                     SourceField=Customer::Address 2 }

       { [{6393F10D-A0FF-4E7B-AE81-E6A984B1ED85}];1 ;City                ;Element ;Field   ;

                                                     DataType=Text;

                                                     SourceField=Customer::City }

       { [{D2B42495-00F6-4906-A4B1-2A5E73F7254C}];1 ;Contact             ;Element ;Field   ;

                                                     DataType=Text;

                                                     SourceField=Customer::Contact }

       { [{BAFCD676-8601-4144-94EA-56BA5B202A5D}];1 ;PhoneNo             ;Element ;Field   ;

                                                     DataType=Text;

                                                     SourceField=Customer::Phone No. }

       { [{01C9BE54-E4E6-4949-B964-9A0430D4A2C6}];1 ;CreditLimitLCY      ;Element ;Field   ;

                                                     DataType=Decimal;

                                                     SourceField=Customer::Credit Limit (LCY) }

       { [{2041A5A2-584E-47D4-9DB6-495004D419F9}];1 ;BalanceLCY          ;Element ;Field   ;

                                                     DataType=Decimal;

                                                     AutoCalcField=Yes;

                                                     SourceField=Customer::Balance (LCY);

                                                     Export::OnBeforePassField=BEGIN

                                                                                 Customer.CALCFIELDS("Balance (LCY)");

                                                                               END;

                                                                                }

       { [{F2D72680-C141-4FF5-9874-ADA61EFED87A}];1 ;FaxNo               ;Element ;Field   ;

                                                     DataType=Text;

                                                     SourceField=Customer::Fax No. }

       { [{93F35292-DC24-4ABF-BFB4-1DBD85A61FF4}];1 ;PostCode            ;Element ;Field   ;

                                                     DataType=Code;

                                                     SourceField=Customer::Post Code }

       { [{D38CD468-1A4E-40B9-ABBB-92DCDBED7F34}];1 ;County              ;Element ;Field   ;

                                                     DataType=Text;

                                                     SourceField=Customer::County }

     }

     EVENTS

     {

     }

     CODE

     {

       BEGIN

       END.

     }

    }

  39. Raju says:

    i am not able to run your sample application its return me error at Program.cs class at below line in method PrintAllCustomers()

                foreach (Customer cust in service.Read())

    exception is:-

    " The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs."

    kindly help me to solve it

  40. Raju says:

    I am not able to connect with below url just tell me what i have to do to solve this problem.

    Url = "http://localhost:8000/nav/customer&quot;

    i am getting error:-

    "The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs."

  41. s.todd says:

    I have a little problem with the sample.

    "Then import the codeunit.txt and xmlport.txt into your NAV installation…" -> I can’t seem to find any option to import code objects or xmlports.

    I’m running with a demo license, could that be the reason?

    Also, I only started out with nav today, please be lenient.

  42. Nishikant says:

    hi Kris:

    How do I do to register the web service ‘localhost’ to the console application? The article says I don’t need to use the IIS but how does this work??

    When I am debugging the sample code i am getting an exception at service.Read() the exception is

    "The request failed with HTTP status 400: Bad Request."

    can you let me know what’s wrong with it? How we are going to use this sample code?

    at the same time i am unable to find this

    URL"http://localhost:8000/nav/customer&quot;

    Thanks in advance

  43. Rooky says:

    Hi, i am trying to integrate third party .Net Application with NAV. .Net Application will write the data into MSMQ in XML format and NAV code Unit which Calls XML Ports receive this data and push into NAV. Can any one please help how i can handle Validation failures (like County Code does not exists in NAV) in Dynamics NAV and in my Design.

  44. Raju Bodkhe says:

    Dear Kris Rafnsson,

    Your code example and Article is very helpful to me for insert and update data using  navision business layer  but i am not able to Read data,  i am getting error:-

    The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT))

    i am not able to understand it, i read about this error on net but not found solution. i think it may because

    of below reason:-

    In WebServiceListner Class’s Output method your write

     /// Note:  We need to create and manage the buffer.

    what is the meaning of it and how should we mange buffer

    give me your mail id to communicate with u

    kindly do the needful      

  45. John says:

    hi Kris,

    Your article and code example is very useful to me for Read, Edit and Insert New record, but search functionality for a Particular record is not work for me ………..if u have any idea…………kindly help for it

  46. Vic says:

    hi experts,

    Does someone know or has a tip how to call a codeunit or a function from table using this web services solution for NAV5.0 or is it impossible?

  47. Vic says:

    or MSMQ +NAS is the only possible solution?

  48. navteam says:

    Let me reiterate that this post was originally written before Microsoft Dynamics NAV 2009 was released. Today, the fully supported way to use Web services is with Microsoft Dynamics NAV 2009. The samples in this post can help you "bridge the gap" between 5.0 and 2009, but anything that you do with this in 5.0 might not be fully compatible with Microsoft Dynamics NAV 2009.

    John:

    You can create a third method (or modify the read method). The new method should combine the techniques demonstrated in Read and Insert, by both take arguments (the search criteria) and return results (just like Read in the sample). Not being a NAV stream specialist, the quick solution would be to create a new Table and XmlPort that defines the search criteria. Use the data that is imported to the table to set filters for the Customer data XmlPort before it is exported. Use temp tables for the filter data (if possible) or clean it up when used and/or supply a unique identifier (like a guid) as the key, and let each call create a new guid  – this is to isolate concurrent  calls from each other – which should not be an issue in NAV and due to the lock statement in the processing chain.

    Vic:

    You can create a new method (along Read and Insert) up thru the whole stack

    As the sample is based on using tables and XmlPorts to define the parameters of the operation implementations in NAV, you have to create tables that match whatever parameter profile your operation takes. When it comes to NAV, you just write whatever C/AL code that will do the job you request.

       EVENT WebService@1102601000::DoStuff@1001();

       VAR

         input@1102601000 : InStream;

       BEGIN

         input:=WebService.Input();

         XMLPORT.IMPORT(XMLPORT::WebServiceDoStuffInput, input);

        // use input from table (if input is needed)

        // now do some business logic like call a codeunit or a function from table

        CODEUNIT.RUN(CODEUNIT::"DoStuff”….  

       END;

    All this functionality also comes out-of-the box in NAV 2009 – so that’s another possibility 😉

  49. Suraj says:

    Hi Kris Rafnsson,
    I am not able to access the project link
    {
    The implementation is in 2 programming languages: C# and C/AL.
    Please take a look at the provided code sample, for the rest of the information contained in the posting. It can be found here: http://code.msdn.microsoft.com/nav/Release/ProjectReleases.aspx?ReleaseId=896
    }
    Can any one please help to get this Sample code..??
    i have to implement similar project..
    Thanks in advance..