Question:
I’d like one of the browses to display immediately after a successful login (as opposed to the user having to click a menu option.) What’s the best way/place of doing that?
Answer:Each frame inside the frameset has a default URL setting. Go to your FrameSet procedure, identify which frame you want to default, and enter the URL in there. Remember you can use a procedure name as a URL.
Question:
I can see the option which requires a person to be logged in in order to see the Form. However if that fails then it goes to the Login window. I’d like it to revert to view-only mode if the person is not logged in.
Answer:p_web.GetSessionLoggedIn()=0
Example 24 contains two examples of this. One via a menu item (direct) and the other as the Save URL of a form.
The URL needs to contain 2 pieces of information. The Action to be taken, and (for some actions) an ID of the record being edited.
The action is passed as one of the following parameters;
?insert_btn=insert
?copy_btn=copy
?change_btn=change
?view_btn=view
?delete_btn=delete
The Copy, Change, View and Delete actions require a unique row ID. This can be created using the p_web.AddBrowseValue method. This method is prototyped as follows;p_web.AddBrowseValue (string proc, string filename, key filekey, <field1Value>, <field2Value>, <field3Value>, <field4Value>, <field5Value>)
'SomeForm?change_btn=change&_bidv_=' & p_web.AddBrowseValue('pageheadertag','mailboxes',MAI:PrimaryKey,2)
W4 (Old): The following answer applied to NetTalk 5.23 and earlier. It is included for comparison during the transition to the new system. The approach documented below will be decremented in a future build.
First, take the case where you’re using a Menu extension. In this case all we need to know is the correct URL, the rest is done for us.
It’s simple, but exact. Because the form is expecting to be called from the browse, it’s expecting the browse to tell it what to do, and on which record to do it. Here’s an example;orMailboxesFormControl?MAI__MailBoxNumber=12&Delete_btn=Delete&
Here’s an example for Insert:
MailboxesFormControl?Insert_btn=Insert&If the form you are calling works on Memory, and not on a file, then the link looks like this;
MailboxesFormControl?Change_btn=Change&Second let’s take the case where you’re placing a link on the window, not using a Menu.
<a href="put the url explained above here">Login</a>
Update: Putting the session Id in the URL is considered a "small" security risk. It is considered better to pass the Session ID via a cookie (which NetTalk already does). So it is not necessary, and possibly not desired, to pass the session ID in the URL.
Syntax error : Unknown procedure labelIn the source the line of the error looks something like this;
ProcedureName(Self)Answer:
This is like going into a tire shop and asking the guy "If I put those tires on my car how fast will it go?" To answer that question the dealer needs to know something about your car. Putting 8 inch retreads on a Ferrari will matter. But putting 30 inch low-profiles on your Datsun isn't going to make it go any quicker.
In the same way, when considering performance, there are a number of factors that have to be taken into consideration.
and so on.
But what's the ballpark? Ok well on my machine (AMD 2600+) I ran various examples. On another machine on the LAN I ran a performance test utility. During the test my CPU went to 100%, which is good, it means we're testing the Server program. I tried with browse pages (16 records), Menus, Forms and so on. In all the tests I ran performance was in the 110-120 pages per second bracket.
So let's say you had 100 users, all getting a page every single second. Well it would cope with that comfortably.
This is with the class still in the beta stage, and running unoptimized code. We expect performance in the future to get even quicker than this.
If you do the filter like this :
'wmu:cust_no=loc:cust_no'
then loc:cust_no would need to be BINDed (_after_ the
PUSHBIND).
however the filter could better be written as
'wmu:cust_no=' & loc:cust_no
(if loc:cust_no is a LONG)
or
'wmu:cust_no=''' & clip(loc:cust_no)
& ''''
(if loc:cust_no is a STRING)
or
'UPPER(wmu:cust_no)=UPPER(''' & clip(loc:cust_no)
& ''')'
(if loc:cust_no is a case insensitive STRING)
and none of these would require binding.
Question:
I have a procedure, that generates a file. I want the file to be sent to the browser. I want this file to be the "whole page" sent to the browser.
Answer:
Remember all a web server does is send files to a browser. So this is a really simple thing to accomplish. But there are some gotchas you need to consider:
The code you need to add is simple.
Question:
I'm planning an app using the NetTalk web server, and I need to record the visitor's IP address. Can you tell me where I might be able to locate the client's IP?
Answer:
The incoming IP number is stored in the header of the incoming GET or
POST.
It is easily accessible from anywhere in your app (that's processing the
page request)
It's stored in
p_web.RequestData.FromIP
Question:
Does the web server functionality work with a multi-dll app? I've given it a try, and the program always fails to initialize?
Answer:
Yes it does work, see example number 20, MultiDLL.
To use the Web Server in a Multi-DLL situation, follow these steps:
In order to logout one of two things needs to happen.
a) If they are inactive for a certain amount of time (NetWebServer.SessionExpiryAfterHS
property) then their session is deleted, and hence they are logged out.
Or
b) In your code you make a call to p_web.SetSessionLoggedIn(0)
Cunningly, if you have the following parameter in your URL then a
logout will be done for you
logout_btn=anything
For examples of Logout techniques see
Logout options are included in the MenuOnLeft procedure. Note that the two logout options here are NOT in the menu itself. You'll find them in the HTML tab under the NetWebPage Settings button.
When you are sending a page to a browser you can embed JavaScript in
the page.
It doesn't matter too much where the Script is, but I usually put it at
the bottom of the page, after the </form> statement.
The code to for a frame to refresh looks like this
<script> top.frames.top_fram.location.reload(true) </script>
Where top_fram is the name of the frame you want to refresh.
Here's an example that conditionally loads the top frame, or the left frame, depending on the existence of a local value.
if p_web.IfExistsValue('loc:no')
packet = clip(packet) & '<script>
top.frames.top_fram.location.reload(true) </script>'
packet = clip(packet) & '<script>
top.frames.left_fram.location.reload(true) </script>'
end
The first thing you'll want to do is to create your own style file. This will allow you to make your own styles, without your styles being overwritten by the shipping NetTalk files.
Question:
In many of the URL's there is a double underscore. For example see question W4 above. What is this?
Answer:
Basic HTML does not allow for a colon (:) to be used in a field name. As a simple workaround NetTalk uses a double underscore in place of a colon. This is translated automatically for you where appropriate. However if you are coding a URL yourself (like the W4 example above) then you need to use a double underscore in place of a colon. For example fil:key becomes fil__key.
If you have an underscore in the name already then you'll need to add that in as well, potentially getting 3 underscores. eg fil:_key becomes fil___key.
If you have a double underscore in the name already then let me know. You're going to have a problem.
Question:
I have an Invoice line item, and I do a lookup on the product code. I'd like the Price from the products file to be entered in the Price field at the same time. (The user can then override the suggested price if necessary.)
Answer:
The easiest place to add extra assignments is by adding them under the More Assignments button. A good example of this is in Example 21. (BrowseInForm). The UpdateLineItems procedure does a lookup on the BrowseProducts procedure.
If you want to do more complicated things, then there is also an Embed point you can use, called AfterLookup.
Tip: Remember when embedding
at this point in the code, you are working on the SessionQueue,
not the actual file field. So If you want to set LIN:Price = PRO:RRP
then the code needs to look like this:
p_web.SetSessionValue('Lin:Price',PRO:RRP)
There is a separate document discussing reports here.
Remember that all NetTalk has to do is convert your existing report output to PDF. So all the normal report questions (how to filter etc) are answered in exactly the same way you would for a normal Clarion report.
If you need to access settings, or parameters, set in the web interface remember that you do have access to the session queue when the report is running in web mode. You can access the queue using the normal syntax. TIP: Since the report can run in normal mode, and web mode, it's a good idea to check if the report is running in web mode, before accessing the session queue. This is done by testing the value of p_Web. For example
If Not p_Web &= Null
! we're in web mode
End
There is a separate document discussing deployment included with the NetTalk documentation.
There is a style file called Error.Css which contains the style used by the errors page. Editing this CSS file is the first option for changing the layout, and style, of the errors page.
If you wish to change the text of the errors page, then override the MakeErrorPage method in the WebServer procedure. The text returned by this procedure contains the HTML sent back to the browser. See example 32.
Tip: Resist the urge to place the name of the missing file in the error message. This can lead to a security problem known as cross-site-scripting.
There're 2 things you need to do:
1: To override the NetTalk4 file update, find the ValidateRecord routine (this will override insert, change and deletes) and put the following code in:
ans = 0
2: You'll need to place the calls to your own filechange method in the ValidateInsert, ValidateUpdate and ValidateDelete methods.
You can add the parameters to the menu URL using the ?a=b&c=d syntax.
For example
'BrowseCustomers?Current=1&Paidup=1'
The first parameter (after the page name) starts with a ? and after that you can have as many parameters as you like separated by a &.
Then in the Browse you need to store this parameter in a session
variable so that the browse remembers it. Remember the browse procedure
itself can get called many times in the life of the browse, so you can't
rely on the parameter always being there. To store the parameter for
later add the following to the top of the GenerateBrowse routine
If p_web.IfExistsValue('Current')
p_web.StoreValue('Current')
End
Then in the browse make use of the SessionValue called Current. For
example
'cus:current = ' &
p_web.GetSessionValue('current')