Background:
I have a page where I have various client-side events being handled with JavaScript. I want to "sync" some of these events with server-side events, or otherwise call functions from the code-behind.
Some of the functions I want to call with JavaScript may make changes to controls (e.g. changing a textbox value) in a form I have on the page. They may also change some values I have stored in the ViewState, as I want some values to persist through postbacks. I do not want to a full postback, and have the controls that may be changed in an update panel.
I am currently "calling" functions in my code-behind with JavaScript by clicking invisible buttons that trigger partial postback on my page through an asynchronous postback trigger in my update panel.
Problem:
One of my client-side events calls a JavaScript function that clicks more than one of the invisible buttons (client-side stuff happens between the clicks that may affect how the the code-behind functions behave). When I have the JavaScript clicking more than one button, the changes made to the ViewState do not seem to persist, and only the changes from the last click are observed.
Example:
I might not have explained this very well, so here is a simplified version of what I have (which I can reproduce the issue with).
Markup:
<asp:Button ID="btnA" runat="server" style="display: none;" />
<asp:Button ID="btnB" runat="server" style="display: none;" />
<div style="background: red; width: 100px; height: 100px;" onclick="AB();"></div>
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel runat="server" ID="upForm" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnA" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="btnB" EventName="Click" />
</Triggers>
<ContentTemplate>
</ContentTemplate>
</asp:UpdatePanel>
JavaScript:
function AB() {
$('#<%= btnA.ClientID %>').click();
$('#<%= btnB.ClientID %>').click();
}
Code-behind:
Protected Sub btnA_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnA.Click
ViewState("AB") += "A"
End Sub
Protected Sub btnB_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnB.Click
ViewState("AB") += "B"
End Sub
Questions:
I've managed to get it working for my case, but I think some of the options other users have suggested could have worked for me as well. Since my case seems pretty unique (partly because it's a hack method), I've included some other suggestions in this answer for future reference.
Since the JavaScript is simulating two buttons being clicked, two consecutive partial postbacks are made. The second request is fired before the first one is returned, and so the second server event grabs the old ViewState rather than the updated one from the first event.
Since my client and server events did not have to be perfectly in sync (it only needs to appear in sync to the user), I reorganized the code behind functions so that only one partial postback was needed per client event, while still keeping the logical flow of events. To be clear, this is more a workaround than a real solution.
Daniel recommended using page methods, which I've taken a (brief) look at and it seems like it might work. To move away from update panels for me at this point and put the page back together again with his suggestions though would take quite a bit of work due to what's already on the page. I might come back to this in the future though and try it out (or maybe use it for something else). Some more details on using jQuery to call page methods and consume web services.