Bug theater in Web services #2

  • Post category:Development
  • Post comments:6 Comments
  • Reading time:6 mins read

imageThe bug with which I started this series is nothing critical. It manifests rarely, you can easily work around it. It’s in the “so what” category.

But the one I’ll talk about today is a tough beast, with not-so-easy workarounds that cause as much headache as the bug itself.

So, here comes bug #2: setting a date to 0D.

Problem

Try it. Expose a page, which includes a date field, as a web service, then try setting it to 0D value. No way you can do it.

Consider this:

SalesOrder_Service svc = new SalesOrder_Service();
svc.UseDefaultCredentials();
SalesOrder order = svc.Read("1000");
order.Posting_Date = DateTime.MinValue;
order.Posting_DateSpecified = true;
svc.Update(ref order);

 

This won’t work, and yet, it’s the equivalent of writing this in C/AL:

SalesHeader.VALIDATE("Posting Date",0D);

 

Of course, this works in C/AL. Why it doesn’t work when invoked through Web services, beats me. NAV simply keeps the value as it was earlier. So, once you write a date, it’s there to stay.

Workaround

Well, obviously you’ll need to write some kind of a function which you can call, and tell it which date field in which table, for which record, should be set to 0D. But as there are a hundred ways to skin a cat (no animals were harmed during writing of this post), there are a hundred ways to set a date to 0D.

One of the obvious ones might be to publish a codeunit with a method which receives the RecordID of the row which must be updated, and the ID of the date field which must be set to 0D. This seems the simplest, because it’s easy to pass the RecordID (thanks to GetRecIdFromKey method of any page Web service), and it could be generic – covering all date fields of all tables with a single function.

Then this piece of code would do the trick:

// RecID is a RecordID variable
// tRecID is a text parameter
EVALUATE(RecID,tRecID);
RecRef := RecID.GETRECORD;
// iFldID is an integer parameter
FldRef := RecRef.FIELD(iFldID);
FldRef.VALIDATE(0D);
RecRef.MODIFY;

 

Well, at least, it will do a trick. Not the one you expected, though.

Trust me, you are not ready for what this thing will do to your data. It will set the date to 0D alright, but it will also reset all the non-key fields of the record to their default values. Now that’s something.

So, that having been eliminated, what else can you do?

You could try with RecordRef, creating a more complex way to tell this generic function which date field in which table you want to update, and for which record, because – interestingly – the code above wouldn’t make a mess if RecordRef was obtained through GETTABLE or OPEN functions. It only happens if it was obtained through RecordID.

In Stratus, we didn’t want to gamble with RecordRef for 0D, so we’ve skinned the cat a different way around. We’ve utilized our extension codeunit builder, and automatically built an extension codeunit which has as many functions as there are date fields that we wanted to update, each of which explicitly sets this or that specific date field in this or that specific table to 0D.

If you have a better workaround, please don’t be shy, share it here (or elsewhere).

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 6 Comments

  1. Mark Brummel

    0D is stored in SQL as 01-01-1753. Isn’t there something you can do with that?

    1. Vjekoslav Babic

      @Mark: no, that won’t help, you can’t do anything by that.

    1. Vjekoslav Babic

      @Soren: thanks for that! I figure I should follow Waldo’s updates more frequently 😉
      However, hotfixes are not always the solution, and sometimes you can’t upgrade just like that.

  2. Peter

    Have you tried: RecRef.GET(RecID) ?

Leave a Reply