This week we are going to look at a couple of WebDev tips. First we will look at some issues with AJAXExecute and the values of edit controls, and then we will look at how to avoid a long report timing out when you run it from WebDev.
First let’s talk about AJAXExecute. AJAXExecute allows you to run server code from browser code. In WebDev there are a few different types of AJAX you can use.
First there is automatic AJAX. When looking at the code editor, you will notice most server code events allow you to make them AJAX calls.
What exactly does this mean? When a call to server code is made, if it is AJAX enabled then the screen doesn’t reload. Which gives the users a much smoother interface and experience. This mode of using AJAX is called Automatic, because literally all you do is turn it one for the code. One mouse click and WebDev takes care of the rest! This mode handles 80 – 90% of my needs, and is the mode I use most of the time.
However on occasion I need to actually call server code directly from the browser code. One example of this is when I want to do something when the user exits a edit control after making a change. There is no server event for this, only a browser event, so my code has to be browser code. When that is the case, we have two functions AJAXExecute and AJAXExecuteAsynchronous.
AJAXExecute is the simplest of these two functions. It calls a server function, that server function must be AJAX enabled, passing any specified parameters. It returns the value returned by the server function. One thing to note is the value returned must be a character string. This is not a WebDev restriction, but a restriction of AJAX technology. This call is very similar to any other function call, execution halts and waits for the called function to complete and then continues.
AJAXExecuteAsynchronous is similar, however as the name implies, it is performed Asynchronously, meaning that the browser code continues running, and does not wait for the server function to complete. This is the function we will be looking at today. Along with the Server function to call, and any parameters to pass, this call also accepts the name of a browser function that will be called once the server function completes. This allows you to have a browser function that will update the page etc. with the results of the function. I rarely need to use this function, but it sure is handy when I do! If the server function you are calling is going to take more than a second or so to complete then you should consider using the Asynchronous call so that the user doesn’t feel that the browser has locked up.
So there’s the good news, you know the bad news is coming right? Like anything else there is always compromises. One of the items we are going to look at today is the fact that values don’t get submited to the server with the call. What exactly does that mean?
If you look at the general tab of a button, you will notice the below option.
When this option is set to “Send the value of controls to the server” then when you reference the edit controls in your server code that will have the values that were on the screen. However, since in our example the button is only executing browser code, the values are not getting submitted to the server. Let’s look at a quick example, to understand this a little better.
Below is a Report prompt from TeamAlogy.com.
As you see the From Date is defaulted to the first day of this month 9/1/2014. Let’s change it to 8/1/2104.
The begin button is making an AJAXExecuteAsynchronous call.
For now, we will just put together a simple RunReport Function. Notice that it is AJAX enabled! Also notice we put a debug break so we can take a look in the debugger.
And when we do it says that the value of the From date is still 9/1/2014. How can that be, we know we changed it?
This is the side effect of not submitting the values to the server. The server never got updated with the changes to the edit control, so it thinks that the value is still the original default value.
There are several ways we can handle this, we could pass the values of the controls to the function, since the browser code where the call is made will have the updated values, but that could get real messy with a bunch of controls. So instead we need a way to get the server updated with the new values, but how.
Well it should come to no surprise for those that regularly follow my blog, a hidden button is part of the solution. Remember we discussed early that a button has the option to make submit the values to the server. So we need a button to do that. We can’t make it part of our Begin button because the browser code will run before the server code does, so the values still won’t be submitted in time.
So we add a hidden button (off the page) to submit the values to the server.
And it is configured to Send the values to the server.
And the last step is we need to AJAX enable the Server Code Event. Otherwise we will get a page refresh which will defeat the whole purpose of our plan.
Note: In the past I have had issues with this not working without having some code in the server event, but my testing with V19, it appears that is no longer the case, but keep that in mind if you have any issues.
So now that we have a button that will submit the values to the server, what do we do with it? Remember I mentioned that edit controls don’t have a server event, only a browser event for when the user exits the control after changing the value. Well all we need to do is “press” the button when that event occurs. And once again thanks to WebDev that is simple.
Now if we repeat our test, we will see that the server code is now getting the updated value.
Before we move on, we need to cover a few additional things.
If you take a look at that screen at design time, you will notice there are a number of controls, but it is only the two edit control that I need to add the special code to press the submitvalues button.
Why is that? Most of them are combo boxes, Lets take a look at the code events behind one of them.
Notice that the combo box control has a server event, that we can AJAX enable. And remember earlier I said, WebDev does all the hard work for us, just by AJAX enabling the code, well it also submits the values, because it knows we would expect them to be updated. So there is no need to press the “Submit Values” button.
Now there is one little trick to this, and if we look at the code behind the check box we will see it.
I don’t actually need to do anything when the Check box is clicked, however in this case WebDev “outsmarts” us, if there is no code in the AJAX enabled event it apparently doesn’t bother to submit the values. So I had to add some “dummy” code to the event so the values would be submitted.
So you may be wondering why I went through all of this “hard” work in the first place. And that brings us to our second topic of the day. Reports that take a long time timing out, and causing a browser timeout error.
There are two time out values that we are concerned with on a WebDev Dynamic site
The first is the Discount the idle users since setting, By default this is set at 20 minutes. This is how long a WebDev dynamic site maintains the state of the connection with a user before it assume that user has “gone away”. Every connection the server is maintaining require memory and resources of the server, so you want this value to be as short as possible. On the other hand if you make it to short, then a user that spends to much time on a screen before doing something that initiates a server event, we have the connection dropped and receive an error. I have covered this issue before in this article
The second timeout “Maximum duration of a request”, tells the browser how long it should wait for a response from the server before it gives up and issues an error message. By default that value is 90 seconds.
This particular report on TeamAlogy.com allows the user to possible pull a large amount of data, with a number of conditions attached, and it is possible for the report to take quite a while to generated. Cause the browser to generate a timeout error if we just called the report directly.
Instead as we have seen in the code of the Begin button, we are instead calling a procedure to run the report using AJAXAsynchornous. This way the browser isn’t “waiting” for a server response, and therefore won’t time out. We still need to let the user know that something is going on, so that they don’t cancel. So lets look at all the code behind the Begin button.
First we display a static that says “Working”
Then we start a browser timer event that calls a browser procedure called AntimateWorking, every 1/2 a second. If we look at the code of that procedure.
It simply rotates through a number of captions for the static, to give the impression of animation. The last thing it does is call the KeepAlive browser procedure, which if you read the article reference above, you know calls a server procedure so that the server knows that the user is still connected.
So now we have the report running as an AJAX Asynchronous event, we have the user watching a screen with a animated “Working” graphic so they know something is going on. The only thing left to do is handle the report once it completes.
Remember this second parameter of the AJAXExecuteAsynchronous statement is the browser procedure to run once the server function completes. In our case that is a broswser procedure called ReportDone. So lets look at that code.
If you look in the help for AJAXExecuteAsynchronous you will find that the browser procedure is always called with two parameters, the first being the result of the server procedure, and the second is the name of the server procedure. This allows you to write a generic “callback” procedure to handle all of your returns from AJAXExecuteAsynchronous calls.
In this case the server procedure returns the name of the file generated by the report. Depending on the options selected that is either a PDF file or an XLS file. So it sets another hidden entry field (ReportFileName) equal to the returned file name then it presses yet another hidden button called “btnCloseWindow”. The code behind that button closes our Dialog Page, returning the name of the report to the calling page.
Notice that this code is not AJAX enabled, in fact we would get a compile error if we tried to call PageCloseDialog from AJAX enabled code. Since it is an actual page closing the page must be refreshed, since it will be a different page.
So what is ever done with that report file name? Well there is a timer in my main menu page that takes care of displaying that report when it detects a return from printing a report. But that code is for another day! As the great P.T. Barnum use to say “Always leave them wanting more” “-)
Be sure to go over to wxLive.us and watch the Uncle Pete’s corner webinar that is the companion to this article.
Uncle Pete’s Corner is webinar series on all things WX, to watch the recorded version of this webinar, many other WX related webinars or to watch future ones live go to wxLive.us