Creating Notifications in Code

AntHillMobAntHillMob Member Posts: 79
edited 2009-06-03 in NAV Three Tier
I am trying to create a notification in the RTC that is generated by an event in the system as well as notes entered by users against a record. Basically I am trying to automatically create a notification to prompt an Account Manager to review a customer record if they exceed terms.

After a little investigation I have worked out that everyting need tor this is held in the Record Link table and I have basically got this working but with two small problems.

1) The actual note/comment is a BLOB field. I assumed I could write the comment to the using OUTSTREAM and WRITETEXT. This appears to work in that I can read and write from it in code but I access the notification in the RTC I get a 'Unable to read beyond the end of the stream' promptly followed by the RTC crashing and burning! What is special about what is written to the note field.

2) Populating the URL field. I can set this so that clicking the Notification opens the correct page but not on the correct record. I orginal assumed thsi was Handed by the 'record ID' field but this appears to make no difference. I have worked out (Ok looked up in the help) the format of the URL and have everything sussed except the bookmark portion. This must be what causes the page to open on the correct record. The help only appears to detail the 'currentposition' part of the url which appears to relate to classic forms. What is the best way of generating this URL.

Many thank in advance for any help anyone can offer.

Answers

  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    1) not sure - but have you tried both binary and text mode - sounds like a null termination is missing or something like that.
    2) the bookmark is retrieved using FORMAT(recordref, 0, 10) (used this in a number of samples on my blog)
    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.
  • AntHillMobAntHillMob Member Posts: 79
    Freddy

    Thanks for the reponse;

    In case anyone else wants to try this...

    1) Finally worked this out - I thought for ages that it was a string termination issue but it's not. The first character determines the length of the string by it's decimal ascii value #-o If this character signifies that the string is longer than the following characters it causes the 'end of stream error'. If it's less (and this is how I finally stumbled on the answer!) then it truncates the string. Of course why it works this way is still a mystery...

    2) I think you mean FORMAT(recordref.RECORDID, 0, 10) - worked it out from your Blog. It only works in the RTC, which caused me a little confusion when I was trying to test my code, but makes perfect sense when you think about it.
  • vshalvshal Member Posts: 11
    Hi,

    Can you tell me how you resolved the 1st one, I am not able to figure this one out and I am getting the same "End of Stream" error in RTC.

    //
    1. Finally worked this out - I thought for ages that it was a string termination issue but it's not. The first character determines the length of the string by it's decimal ascii value #-o If this character signifies that the string is longer than the following characters it causes the 'end of stream error'. If it's less (and this is how I finally stumbled on the answer!) then it truncates the string. Of course why it works this way is still a mystery...
    //

    Thanks,
    Vishal
  • AntHillMobAntHillMob Member Posts: 79
    I've seen a different answer somewhere else in the forums, but this one worked for me and if you examine the text strings created by a note with a hex editor this is what they appear to be doing.
      Note.CREATEOUTSTREAM(OutStream1);
      chr := STRLEN(MessageText);;
      OutStream1.WRITETEXT(FORMAT(chr) + MessageText);
    

    Where 'chr' is a variable of type character and 'MessageText' is the text you want for the notification.

    Ususal disclaimers about using as your own risk apply :wink:
  • AntHillMobAntHillMob Member Posts: 79
    I've seen a different answer somewhere else in the forums, but this one worked for me and if you examine the text strings created by a note with a hex editor this is what they appear to be doing.
      Note.CREATEOUTSTREAM(OutStream1);
      chr := STRLEN(MessageText);
      OutStream1.WRITETEXT(FORMAT(chr) + MessageText);
    

    Where 'chr' is a variable of type character and 'MessageText' is the text you want for the notification.

    Ususal disclaimers about using as your own risk apply :wink:
  • vshalvshal Member Posts: 11
    thanks for the response, I will try this one out.

    Now I am wondering how to create the URL1 (link to the Page) in the Record Link Table, I m sure there is way to do it :)

    Vishal
  • vshalvshal Member Posts: 11
    Hi,

    I have this working and not working, at times I get the same error message and the RTC crashes....sometimes it works...what I have noticed is that :
    1. when I put a smaller string into the messagetext it seems to be working
    2. when I make up a string by adding varialbes together it works if the length is smaller
    3. When the length in the variable is longer it seems to crash.

    Is there a limitation on the length of string in the message text variable ?

    thanks a ton for your help so far, appreciate it.

    Regards,
    Vishal
  • AntHillMobAntHillMob Member Posts: 79
    To create the link (for this example a customer card):
      RecRef.GETTABLE(Cust);
      "Record ID" :=  RecRef.RECORDID;
      IF ISSERVICETIER THEN
        RecordLink.URL1 := 'dynamicsnav://///runpage?page=18&bookmark=' + FORMAT(RecRef.RECORDID, 0, 10) +
        '&mode=view'
    

    Where 'Cust' is a record of type customer (positioned on the record you want to create the link to).


    With the text the first 'character' determines the length of the following string. If the string is shorther that the character designates this is where you get the crash. If it is longer it will not crash it will just truncate the text. The 'STRLEN' is key so if you are concatenating strings make sure you are checking the Strength length of the 'final' string.
  • vshalvshal Member Posts: 11
    Hi,

    Thanks for the response.

    Do you know how to get the page id to be dynamic rather than static in the link ?

    for eg, i changed the payment terms on the vendor and notification was generated for it, this would need the page id for the vendor card.

    Regards,
    Vishal
  • TonyHTonyH Member Posts: 223
    I did actually create this, and it worked like a charm, however, it is flawed.

    Our process was that when a user modified, inserted or deleted a record it notified, with a link to the document and comments.

    However, the comment became a problem I would load up RTC and get an error "Could not read past the end of the stream"

    Here is the case summary to help you out.



    Scope
    You had developed some custom code to write the value of a BigText variable to the RecordLink.Note blob field. On opening the RTC Role Center, the UI returns an error..."Could not read past the end of the stream", yet notes entered manually via the RTC will display normally and without error.

    Assessment
    Per Development...

    This problem is related to databinding. Today in the NoteColumnBinder data is serialized/deserialized using strings with the BinaryReader/Writer class (.NET). Serializing strings prepends the stream with the length of the string. However the CodeUnit in the repro steps will not copy the length when copying the Note. This means that when the RTC tries to deserialize the note the bytevalue of the first character will be treated as the length of the note and the EndOfStreamException occurs. A small example may clarify..

    RTC writes 'Test' which is 4(length) 84 101 115 116 in serialized format. AL copies this as 84 101 115 116. RTC then tries to deserialize this as 84(length) 101 115 116. Since the note is only 4 characters and not 84 it will try to read past the end.

    ---

    The short answer is that the content of the BLOB in the Note field is an internal format to the RTC, and it was not designed to be used from C/AL.

    For now, you can work around the problem, by simulating the .NET serialization format. You could also try to mimic the serialization format from C/AL, but the safest workaround would be to let .NET serialize/decerialize the string. You can do that by creating a com-callable .NET class to serialize/decerialize, and then use that from C/AL.
  • AntHillMobAntHillMob Member Posts: 79
    Vishal,

    Sorry left out the line
    RecRef.SETPOSITION(Cust.GETPOSITION);
    

    The line 'FORMAT(RecRef.RECORDID, 0, 10)' is the key as thsi special format instaruction returns the bookmark!

    This will then open the card at the releveant record.
Sign In or Register to comment.