Nov 21, 2012

Detecting multiple postbacks using Ajax Update panel

There is  Ajax update panel.
You have a textbox with Autopostback server side logic inside panel.
There is also submit or Save button that of course creates Postback.

The problem may and may not show up its ugly face depending on server response time.

So good practice is to put some sleeping in your server side:

Threading.Thread.Sleep(1000);

Make some changes in your textbox and WITHOUT leaving field select Save button.
At this moment:
- Autopostback of textbox fires and reaches first server side
- standard postbak generated by Save is IGNORED since there is still active postback from textbox

Bad news is that no errors is raised and your logic for saving data behind Save button is completely ignored.
So user leaves form been sure that content is saved.

Here is a patch not a solution since is quite ugly but at least makes sure that everyone what happened.

Replace your server side button with standard html input and fill onclick event:

<input type="button"  value="Save" onclick="return Save('btnSave')" />          

Important! Place this button OUT of Ajax update panel tag :


     </ContentTemplate>    
</asp:UpdatePanel>
...
<input type="button"  value="Save" onclick="return Save('btnSave')" />          

Now write some javascript on page:


function Save(updatePanelId) {  
    if (!WaitForAnsycPostback()) { return; };

    var requestManager = Sys.WebForms.PageRequestManager.getInstance();

    __doPostBack(updatePanelId, "save");
};

function WaitForAnsycPostback() {
    var requestManager = Sys.WebForms.PageRequestManager.getInstance();

    if (requestManager.get_isInAsyncPostBack()) {
        alert('Please save again');
        return false;
    }

    return true;
};

Idea is  to ask Ajax PageRequestManager "Hey is something already going on?".
If he confirms we should inform user.
Yea I know its ugly but its a patch not a solution.
Ideally we should create some sort of queue and wait but this is safer.

And of course once you manually do postback like we did:

    __doPostBack(updatePanelId, "save");

; you must handle it differently in your PageLoad:

        If Not Me.Page.Request.Params Is Nothing AndAlso Me.Page.Request.Params.Count > 0 AndAlso _
            Not Me.Page.Request.Params("__EVENTARGUMENT") Is Nothing AndAlso _
            Not Me.Page.Request.Params("__EVENTTARGET") Is Nothing AndAlso _
            Me.Page.Request.Params("__EVENTARGUMENT").ToString().ToLower() = "save" _
            AndAlso Me.Page.Request.Params("__EVENTTARGET").ToString() = "btnSave" Then
            btnSave_Click(Nothing, Nothing)
            Return
        End If

And have in mind important issue that your Save button control ID is unique.
By default when using server side button ASP.NET takes care about this generating those ugly ctl00__  names.
Now you should take care of it.


Read more here:

















No comments:

Post a Comment