Recently, I had to create a form that contained a list of smaller forms so that the user will submit a multiple insertion of objects. There were a lot of submit buttons and a Silverlight file uploader. Given the presence of the file uploader, all submits needed to be handled asynchronously. I thought it would be a good idea to use the update panel control for this scenario. Also, I added a trigger so when the file upload completed, a button was clicked and thus an update panel was refreshing without user interaction. Pretty neat, but soon I faced the ugly truth.
If two asynchronous requests overlapped the first was somehow killed and never completed. In many cases, while uploading 4 or 5 files, only 3 rows made it to the database! I googled a bit and I stumbled upon this article http://weblogs.asp.net/akhhttar/archive/2009/08/26/simultanious-async-requests-using-multiple-update-panel.aspx.
Unfortunately, it was the only article that mentioned this behavior. What the article suggests is that you can check if there is an asynchronous request in progress so that you can cancel the new request. Not a solution of course, but it is all I had. In my scenario, informing the user that his request cannot complete and to try again later is unacceptable, since my user is (most likely) not in front of his screen.
So I had to implement a queuing mechanism, so that all request will execute in proper order. So far it works nicely and time will tell if this solution is a keeper.
The whole process is rather simple. Every button that wants to refresh an update panel, calls the register_button(..)
function instead. This function adds the button to a queue, and then calls the function that checks the queue. If there is not a pending request, a button is removed from the queue and then clicked.
var all_btns = new Array(); var position = 0; var request_pending = false; var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_beginRequest(BeginRequestHandler); prm.add_endRequest(EndRequestHandler); function BeginRequestHandler(sender, args) { prm._scrollPosition = null; } function EndRequestHandler(sender, args) { request_pending = false; upload_files(); } function register_button(btn_id) { var total_items = all_btns.length; all_btns[total_items] = btn_id; upload_files(); } function upload_files() { if (!upload_pending) { if (all_btns[position]) { position = position + 1; request_pending = true; document.getElementById(all_btns[position - 1]).click(); } } }
After googling on this a bit more, I found a few threads at http://forums.asp.net/. You can check them also:
Leave a Reply