Reimers.dk

.NET, AJAX and Google APIs brought together
Welcome to Reimers.dk Sign in | Join | Help
in Search

Jacob Reimers Weblog

Tweaking the ICallbackEventHandler and Viewstate

In this post I am going to explain a basic way to add updated state information to an ASP.NET page. As I will get into later the default state management is not created for AJAX functionality and Microsoft's callback features need some tweaking to perform according to the AJAX philosophy. But with some slight tweaking you can get the quick (and somewhat hyped) response of AJAX as well as the page persistance of ASP.NET.

One of the big things in ASP.NET is Viewstate. Some people turn it off by default and others write long rants about how it eats up bandwidth. But if you want to overcome the problems caused by the statelessness of HTTP there is really no other way than to save the information with the client. Yes I know there are other options for storing viewstate, but by far the most common is on the client page, and if you want non-expiring state this is where you would save it.

My view on viewstate is that the extra (kilo)bytes added to a page by the viewstate is hardly any real problem with modern broadband connections. A much larger problem is that it is not possible to update the viewstate on the client or on the server when doing callbacks. This basically means that anything you do to a control during a callback will not be recorded in the viewstate, even if you explicitly call: Viewstate["Something"] = newValue; But then again ASP.NET has always been about postbacks.

To further confound this problem is that when doing callbacks using the ICallbackEventHandler the "original" page is the one being dealt with on the server. By original I mean that any changes to the page (ex. text changed in textboxes) is not recorded when the page is being posted to the server.

"Wait a minute" I hear you say. Posting the page? I thought this was callbacks. Well in fact to handle the client's information and not some new generic information it is necessary to post the page to the server. The information is in fact not the state of the page when the callback is generated but a snapshot of the page right after it has finished rendering. You can test this by implementing ICallbackEventReference on a page and have the callback return the text value of a textbox. Now type something into the textbox and trigger the callback. You should see that it spits out the value of the textbox when the page was loaded.

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.

The second obstacle with a little clientside coding to tweak the ICallbackEventandler generated code. By default the post information is generated when the page first loads (which explains the snapshot of the initial page). The WebForm_InitCallback() function prepares this snapshot and stores it in a variable called __theFormPostData. So if you want to have the changed page sent to your server instead of the original then you have to reset the __theFormPostData variable and re-run the WebForm_InitCallback() function before running the callback function.

JavaScript

__theFormPostData = ''; WebForm_InitCallback(); DoCallback(argument, context);

This ensures that the post data is updated just before the callback is sent off and the server will receive the updated values of textboxes etc.

The first obstacle (read-only viewstate) is more difficult to overcome. The viewstate is created using the LosFormatter. But in order to prevent tampering the viewstate holds Mac Address information. Trying to tamper with the viewstate is not something I would recommend. Both for the reason above and for the simple fact that the LosFormatter requires full trust on the server to run (because it uses reflection to do the serialization). If you are developing for an unknown environment then you can't assume that the user will have full trust for his web application as most web hosters will not allow this.

But there is nothing wrong with writing your own state management system and turning off viewstate. A simple state management system is a Dictionary<string, string>. It functions in much the same way as the viewstate except that it handles only string values instead of objects. The reason I prefer strings is that they are easy and safe to serialize. As mentioned above you cannot presume that the user has the option to use serialization methods that use reflection, so you are basically left with only XML serialization. But the XmlSerializer works fine on Dictionary<string, string> so all is not lost. To ensure that the dictionary values are always kept updated the serialized dictionary should be returned to the client with the callback result and the field that holds the state information updated.

Published 23. marts 2007 10:55 by jjrdk
Filed under: ,

Comments

 

hubert said:

So if I've understood this, the ViewState during a callback is stale if the client user has entered data into fields. Bummer, since that is why that never worked :-) And, you suggest using a JS Dictionary on the client? Or somewhere else? If the Dictionary is in the code-behind, then where, since  we server side pages are cached differently according to IIS/.NET settings...

Thanks!

april 2, 2007 10:59
 

Jacob Reimers Weblog said:

I recently published some new web controls. At the same time I took down the old extended web controls since I found an easier way to get the same functionality through the standard ASP.NET controls. I will get into that later. The new web control collection

april 3, 2007 04:15
 

jjrdk said:

april 3, 2007 04:16
Anonymous comments are disabled