Strange Web services behavior in NAV

  • Post category:NAV
  • Post comments:7 Comments
  • Reading time:5 mins read

bugorfeatureA bug or a feature? Sometimes it’s hard to tell for sure.

Web services are a fantastic tool in NAV, however, they do not always behave exactly as you would expect them to. There is one particularly annoying behavior, which just after you get used to it starts getting even stranger.

So, setting any numeric value during the Create method call on any page web service will have no effect, and the only way to set a value in a numeric field would be through a subsequent call to Update method.

I know I promised I wouldn’t write code here in my blog, but this post simply wouldn’t work without it. So, expose Page 253 Sales Journal as a web service, and then try this simple code:

SalesJournal_Service srv = new SalesJournal_Service(); <br />SalesJournal jnl = new SalesJournal(); <br />jnl.Posting_Date = DateTime.Now.Date; <br />jnl.Account_Type = Account_Type.G_L_Account; <br />jnl.Account_No = "7150"; <br />jnl.Document_Type = Document_Type.Invoice; <br />jnl.Document_No = "TEST123"; <br />jnl.Amount = 1000; <br />srv.Create("DEFAULT", ref jnl);

 

When you execute that, this is what you get in NAV:

wsexample01

Take a look at the Amount field. It’s zero, even though I explicitly set to 1000. Also, notice that Document Type is empty, even though I actually set it to Invoice. Yes – options are numeric, and they exhibit exactly the same stubbornness in Web services.

Now, change the code slightly:

jnl.Posting_Date = DateTime.Now.Date; <br />srv.Create("DEFAULT", ref jnl); <br />jnl.Account_Type = Account_Type.G_L_Account; <br />jnl.Account_No = "7150"; <br />jnl.Document_Type = Document_Type.Invoice; <br />jnl.Document_No = "TEST123"; <br />jnl.Amount = 1000; <br />srv.Update("DEFAULT", ref jnl);

 

Give it some runtime, and your NAV will show this:

wsexample02

Funny. Now both Document Type and Amount have correct values.

And this is precisely how any page Web services, standard or custom, behaves when you set numeric fields during the initial Create call.

If you think this is not a big deal, and you just go and do a Create followed up by an Update, that’s precisely what I thought until a couple of days ago. However, the problem is big. Big time big.

Guess what happens if your primary key contains a numeric value? Precisely! It will be reset to 0. Actually, the only way for a page web service to set a correct primary key numeric value during the Create call is to have AutoSplitKey property set to true, or to have a built-in filter on the numeric field (e.g. Sales Order).

If you don’t have such a filter, and you need to set the numeric value directly, then you’ll have issues. If you are lucky enough that you don’t need 0 as a value in any of the records, then you can create it, and immediately update it, which would result in an expensive rename operation in NAV, but still the job gets done. If you are not lucky, and the 0 is already there in a record, you may get primary key violation and not be able to insert the record at all.

And what if, just what if the table itself prevented renaming? Such as, for example, Default Dimension? Well, yes, sorry but you can’t use that web service.

Of course, there is a workaround: you can create a codeunit, have a function there which inserts the record for you. This would work. However, this will cause issues with transaction integrity, because the call to this function would be executed in a separate transaction. You could expose this codeunit as an extension codeunit, ensuring the transaction integrity, however you would end up using too many extension codeunits which do nothing but fix a bug, each.

I don’t know if there is a better workaround or a solution to this, but from what I’ve done so far with web services, I’d say no. If you have a solution, or a workaround, which works better than this one suggested above, please share it here.

Vjeko

Vjeko has been writing code for living since 1995, and he has shared his knowledge and experience in presentations, articles, blogs, and elsewhere since 2002. Hopelessly curious, passionate about technology, avid language learner no matter human or computer.

This Post Has 7 Comments

  1. Freddy

    Isn’t this because you need to set jnl.AmountSpecified = true before your initial call to Create (and jnl.Account_TypeSpecified)
    The same goes for all value types – if you don’t set Specified to true, then the value doesn’t get transferred to NAV Web Services, this is a behavior of the proxy classes generated by Visual Studio.
    When you get the record back from NAV – all value type fields will have their corresponding Specified field set to true and thus you can modify and send it back.

    /Freddy

    1. Vjekoslav Babic

      @Freddy: Absolutely, that was it. My googling for the solution wasn’t efficient – but now that I knew exactly what to search for, I see that you blogged about it a year and a half ago, and that there is a MSDN article precisely about this issue. Funny .NET behavior… having checked the proxy class itself, it might have been a very simple trick to simply assign the Specified property automatically during assignment of any applicable field – since they are using access methods, and not purely exposing member variables. It’s a relief to see that this is a .NET known issue, and not a NAV Web services one. Thanks!

  2. QQ

    why do other values work though?

    1. Vjekoslav Babic

      @QQ: Actually, they didn’t just work. String values are always passed if they are different than null. Date was not sent, but was set to workdate automatically by NAV.

  3. Nuno

    Hi,

    if you have multiple journal templates how you choose the journal template to use when you make call the create method? we don’t have the field on the xml side.

    thanks

    1. Vjeko

      @Nuno – do the tips from my last post help? There I explain how you can overcome certain limitations. Selecting a template should not be more complicated than passing the flow filters to a page.

Leave a Reply