Call Codeunit from C# - is a callback from NAV possible?

JutJut Member Posts: 72
edited 2012-03-01 in NAV Three Tier
Hallo,

Another question just arose when I was thinking about possibilities of NAV 2009 and webservices. Let's assume that I expose a Codeunit with a function via the Webservice-Table. This function then calls a number of other functions in NAV whereas some paths are not determined up front, in NAV this would normally be handled with Confirm-Dialogs. This is the NAV side. Let's imagine that a .Net-Application consumes this codunit by using the related webservice. Is it now possible in the NAV-Codeunit to retrieve some information from the calling .Net-Application in order to simulate a Confirm-Dialog for example? I could think of three and a half ways that all do not seem perfect to me. The first one would be to use some kind of COM-Object in NAV to communicate with the calling application. It might also be possible in NAV to assign a flag to a field like WaitForConfirm in a new table. The .Net-Application then would just need to listen to changes in this table. The "response" i.e. the decision of that simulated confirm-request would be stored by the .NET-Application in a second field in that table. As soon as NAV finds this answer, it could continue its function-calls. I think that an asynchronous call of the webservice would be necessary for this solution.
The third solution would be to force decisions of all Confirm-Request before the Codeunit is called. This of course is not very practical because it is not clear which confirm-request would be called before the source-code is actually executed.

Or as another more theoretical idea would it maybe be possible to modify the managed C# that is automatically created? All confirm-requests would then be replaced by another function-call that handles the dialog.

Well, maybe I am really on the wrong track or overseeing something simple but I don't see a better solution. I would be interested in your thoughts on this.

Regards,
Jut

Comments

  • kinekine Member Posts: 12,562
    It is same like when using same code from NAS. There cannot be any confirm in the code when the code is called from WebService. Each confirm in this case must have some "default" answer which will be used during execution. You need to use GUIALLOWED variable to make the confirm conditional. You can use the ISSERVICETIER to look if you are running as WebService (GUIALLOWED will be False and ISSERVICETIER will be True). And there cannot be any communication between calling app and the webservice after the webservice is called. You need to pass all parameters as part of the call if you need. You cannot e.g. "Pre-set" the optionsby another webservice call because each WebService call is called without any context of other calls (e.g. to be able to use Singleinstance codeunit...)
    Kamil Sacek
    MVP - Dynamics NAV
    My BLOG
    NAVERTICA a.s.
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    Correct - and No, you cannot make callbacks from your NAV WebService in 2009.

    Another thing to keep in mind is, that one WebService method call is one transaction - so you want to keep these things of a size, where you know what is going on.

    One WebService method call being one transaction has the advantage that if somethings fails - everything rolls back - and btw. COMMIT's are ignored in a WebService context.
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • JutJut Member Posts: 72
    Hmm, I was again playing around with two different Web-Services - Customer Page and Contact Page.

    My idea was first to create a new Contact in async-mode. In a trigger (Adderss - Onvlidate) in my Contact-Table that is called from this Webservice, I had a sleep(2000) statement to wait two seconds. After the sleep-statement I made a Customer.GET-Statement for a customer #78100 that should not exist at that moment the Create-Async(cont)-Method is executed. The next C# statement was an async-call of the Customer-Webservice method to create a customer with # 78100. The C#-code looks like:
    ContWS.Contact_Service contProxy = new ContWS.Contact_Service();
                CustWS.customer_Service custProxy = new CustWS.customer_Service();
                ContWS.Contact cont = new ContWS.Contact();
                cont.Address = "Address of Contact";
                contProxy.CreateAsync(cont);        
                CustWS.customer cust = new CustWS.customer();
                cust.No = "78100";
                cust.Address = "Address of Customer";
                custProxy.CreateCompleted += new WindowsFormsApplication1.CustWS.CreateCompletedEventHandler(custProxy_CreateCompleted);
                custProxy.CreateAsync(cust);
    

    In the Contact-Table in the OnValidate-Trigger of the field Address I do have the following source code:
    SLEEP(2000);
    
    IF Customer.GET('78100') THEN
      "Address 2" := Customer.Address;
    

    After my C#-Code is executed, the field "Address 2" of my Contact has the same value as the Address-field of my Customer i.e. "Address of Customer". Does this mean that the Contact-Webservice was able to perform a dirty read of the record that was going to be created by the Customer-Webservice or when and how have the database-transactions taken place in my example?

    Regards,
    Jut
  • DenSterDenSter Member Posts: 8,307
    What you are doing is articifially splitting transactions in half, and deliberately leaving inconsistent data in place. You have to be REALLY careful with that approach, it is easy to completely screw up data integrity that way. Doing this with master records like Customers ot Items is not a big deal, but as this grows into more complex transactions, it's not a far stretch to imagine half-posted invoices out there.

    Webservices are not an API, and you should not try to make it behave like it. Instead of splitting up transactions, you should find a way to make what you want to do into one transaction, and figure out a way to pass parameters into that process, and return a success flag or something.
  • JutJut Member Posts: 72
    You are absolutely right about the risk that lies in splitting transactions. But well, it is a question of trade-offs (e.g. commits in batch routines) and sometimes of the sole possible solution. In my case the trade-off would be to lose code-reusability. I can't change it that standard NAV uses many confirm-dialogs and as I try to make these functions available to the out-of-nav-world I prefer this solution rather than rewriting many parts of the application.

    In fact I managed to build my Confirm-Dialog between NAV and C# just by using this logic of async-webservices. I see no risk of inconsistencies if this is done open-minded.
  • DenSterDenSter Member Posts: 8,307
    Trivialize data integrity at your own risk, personally I think it is a very much underrated problem. You are looking at this from a technical standpoint, don't forget that NAV is a financial system first and foremost. If you end up with an invoice that has posted customer ledger entries but failed when G/L entries were processed, you are going to find yourself in a world of problem just figuring out what happened.

    There's a system variable called GUIALLOWED that I've used to set default confirmation values for NAS, I wonder if you could use that for webservices as well. I don't know for sure though, maybe someone else can chime in.
  • JutJut Member Posts: 72
    If there is a big reason for inconsistent postings, then it is the fact that the posting routines are just too far from state-of-the-art. But, well this is another topic. Besides, G/L-related processes certainly won't be the typical scenario of using Webservices instead of the NAV-Client so don't be worried about my data consistency.

    There is indeed a flag ISSERVICETIER that I could use for defaults but I think that default are not always a good idea - especially not in highly interactive systems like Silverlight-applications.
  • kinekine Member Posts: 12,562
    Do not forget that Webservices are not there for "interaction" with the system. It is for calling functions in the system... this is a little difference - interaction is continuous two way process, calling function is only separate question-answer pair. Webservices are not there for building "another Dynamics client", they are there for integration. May be this is the main source of the problem... 8)
    Kamil Sacek
    MVP - Dynamics NAV
    My BLOG
    NAVERTICA a.s.
  • DenSterDenSter Member Posts: 8,307
    That's the point we're trying to make, but it's not making much of an impression :-k
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    I totally agree with the observations DenSter and Kine are stating here - my experience from working with Web Services tells me that high level functions, performing a task is better exposed than a number of small routines.

    Reg. ISSERVICETIER - I would like to add that ISSERVICETIER is true for both Web Services and the Role Tailored Client - and should be used when handling differences between C/AL and C#.
    Another function is GUIALLOWED which should be used when you want to show a dialog or like. Note that GUIALLOWED will be false for both Web Services and NAS.
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • julkifli33julkifli33 Member Posts: 1,092
    hi all...
    why i cant do commit using webservice?
    i'm using nav 2009 R2

    my scenario is like this :
    i put 3 txt files in a folder, 2 of them is correct
    1 is error...
    if executed successfully must go to folder history
    if error go to folder error

    if i execute run my codeunit, it can import this file 1 by 1
    which is 1st file executed successfully
    2nd file executed successfully
    3rd file cant be executed....
    this scenario is correct

    but if i use webservice (C#), i create looping to execute this codeunit
    1 hit... can execute these 3 files
    but my question is why if i have 1 error file, these 3 files will go to folder error
    but if i put 2 correct files, it will go to history
    weird
Sign In or Register to comment.