views:

1403

answers:

6

I have a problem with maintaining state in an ASP.NET AJAX page. Short version: I need some way to update the page ViewState after an async callback has been made, to reflect any state changes the server made during the async call.

This seems to be a common problem, but I will describe my scenario to help explain:

I have a grid-like control which has some JavaScript enhancements - namely, the ability to drag and drop columns and rows. When a column or row is dropped into a new position, an AJAX method is invoked to notify the control server-side and fire a corresponding server-side event ("OnColumnMoved" or "OnRowMoved").

ASP.NET AJAX calls, by default, send the entire page as the request. That way the page goes through a complete lifecycle, viewstate is persisted and the state of the control is restored before the RaiseCallbackEvent method is invoked.

However, since the AJAX call does not update the page, the ViewState reflects the original state of the control, even after the column or row has been moved. So the second time a client-side action occurs, the AJAX request goes to the server and the page & control are built back up again to reflect the first state of the control, not the state after the first column or row was moved.

This problem extends to many implications. For example if we have a client-side/AJAX action to add a new item to the grid, and then a row is dragged, the grid is built server-side with one less item than on the client-side.

And finally & most seriously for my specific example, the actual data source object we are acting upon is stored in the page ViewState. That was a design decision to allow keeping a stateful copy of the manipulated data which can either be committed to DB after many manipulations or discarded if the user backs out. That is very difficult to change.

So, again, I need a way for the page ViewState to be updated on callback after the AJAX method is fired.

A: 

Check out this blog post: Tweaking the ICallbackEventHandler and Viewstate. The author seems to be addressing the very situation that you are experiencing:

So when using ICallbackEventHandler you have two obstacles to overcome to have updated state management for callbacks. First is the problem of the read-only viewstate. The other is actually registering the changes the user has made to the page before triggering the callback.

See the blog post for his suggestions on how to solve this. Also check out this forum post which discusses the same problem as well.

Yaakov Ellis
A: 

I actually found both of those links you provided, but as noted they are simply describing the problem, not solving it. The author of the blog post suggests a workaround by using a different ViewState provider, but unfortunately that isn't a possibility in this case...I really need to leave the particulars of the ViewState alone and just hook on to what is being done out-of-the-box.

Rex M
A: 

If you're already shuffling the ViewState around anyway, you might as well use an UpdatePanel. Its partial postbacks will update the page's ViewState automatically.

Dave Ward
A: 

I found a fairly elegant solution with Telerik's RadAjaxManager. It works quite nicely, essentially you register each control which might invoke a postback, and then register each control which should be re-drawn after that postback is performed asynchronously. The RadAjaxManager will update the DOM after the async postback and rewrite the ViewState and all affected controls. After taking a peek in Reflector, it looks a little kludgy under the hood, but it suits my purposes.

Rex M
A: 

I don't understand why you would use a custom control for that, when the builtin ASP.NET AJAX UpdatePanel does the same thing.

It just adds more complexity, gives you less support, and makes it more difficult for others to work on your app.

Dave Ward
A: 

@Dave Ward

That is a fair assessment, the ASP.NET AJAX UpdatePanel technically accomplishes the same thing. However it feels kind of inconvenient since each control that might be updated on an async event has to be wrapped in an UpdatePanel. The RadAjaxManager coordinates these postbacks and updates by itself from an unobtrusive corner of the page. A minor distinction but for my particular purposes I need something that gets out of the way for junior devs that might not be familiar with ASP.NET AJAX.

Rex M