Each ASP.NET 2.0 page, which enables AJAX callback, has to implement the interface ICallbackEventHandler. There are many articles which briefly describes how to do that. My intension is not to repeat the well known story. I would rather focus error handling while performing callbacks in AJAX. If you ever seen the message returned by AJAX you were probably wandering, how the message looks like. If you never seen the message produced in a case of an exception it is time to do it now, because your JAVA-Script AJAX error handler has possibly some problem.
Assume there is a page which implement interface ICallbackEventHandler. That means the page implements following two methods:
- RaiseCallbackEvent and
- GetCallbackResult();
The first method is invoked during processing of the page request in the ASP method ProcessRequest(). After all, the method GetCallbackResult is invoked.
This method is used to prepare the string, which will be retrieved to the client, after the AJAX call has been processed.
At the client side there is always some function which invokes WebForm_DoCallback. After processing of GetCallbackResult at the server side the client invokes one of two possible JavaScript event handlers,
which have been specified as arguments in the call of WebForm_DoCallback. Following code illustrate this:
function ValidateField(validatorInstance) { var box = document.all["TextBox2"]
WebForm_DoCallback("__Page", box.value, OnValidationSuccess, "cde", OnValidationError, true); }
function OnValidationSuccess (message, imageInstance) { alert("eventHandler:" + newValue); }
function OnValidationError(message, imageInstance) { alert("errorHandler:" + message); }
|
The method ValidateField performs the AJAX call. If the call ends successfully the handler OnValidationSuccess will be invoked. If AJAX call fails,
the handler OnValidationError will be invoked. The invocation pattern by successful call looks as shown below:
Client : WebForm_DoCallback Server : RaiseCallbackEvent { do something without error } Server : GetCallbackResult {return "ok";} Client : OnValidationSuccess (message) |
The message returned on the client side is as expected "ok". Now, let's do the same if some error occurs at the server side:
Client : WebForm_DoCallback Server : RaiseCallbackEvent { throw new Exception("Exception");} Server : GetCallbackResult {return "Failure";} Client : OnValidationError(message) |
In this case the message returned by GetCallbackResult contains something like:
"Exception.56|/wEWAwLM2oLGBwLs0bLrBgLs0fbZDC3VMN/DL8xzHgo9Pw1ztfesraLyFailure".
Personally, I find this bad-design. Usually, I would expect the same pattern as in previous example. At the beginning of the message is the text describing the exception.
At the end is the result of method GetCallbackResult. However all I need is exception text (Exception) and nothing else.
The strange text after expected text (in this case Exception) is a length prefixed and HTML encoded event validation field value.
Ups?! It is something you do not need, but you are forced to deal with. Here is where the value comes from:
input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWBQKGg9abDQKd9sHMBgKc9s........" |
This is a hidden field in ASP.NET which deals with post-backs. But, that's not all. This is the case if the page declares the attribute: EnableEventValidation="true".
But if the same attribute is set on false, the result will look completely different:
"ExceptionsFailure"
Ups again?! Is that bug or feature? To understand this second "theory of relativity" I was digging in the source code of ASP.NET and found following in simplified form:
Server : ProcessRequest
PrepareCallback try { yourPage.RaiseCallbackEvent(); Response.Write('s'); } catch(Exception e) { Response.Write('e'); Response.Write(e.Message) }
RenderCallback callBackResult = yourPage.GetCallbackResult(); if (EventValidationEnebled = true) { val = GetEventValidationFieldValue(); Response.Write(val.Length.ToString()); Response.Write(val); Response.Write('|'); } else { Response.Write('s'); }
Response.Write(callbackResult); |
The shown pseudo code describe following: When one request is sent to ASP.NET, then the ProcessRequest is invoked. This method performs many nice things, but it
also invokes the method PrepareCallback. This one invokes your RaiseCallbackEvent. If there is an exception it just appends an "e" at the beginning of the response and finally
appends the message describing the exception.
In the second step, The method RenderCallback is invoked. This one invokes GetCallbackResult. As you see this method will be invoked even if the RaiseCallbackEvent has failed.
After RaiseCallbackEvent the amazing story is started. The ASP.NET checks the attribute EnableEventValidation. Depending on this value different response will be retrieved now.
I do not know why this is required, but it does not seem to be the right thing.
Anyhow, my recommendation is following:
- Implement your callback processing call in the RaiseCallbackEvent. That means use GetCallbackResult just to return the message if the call to has been RaiseCallbackEvent successful.
Otherwise return String.Empty from GetCallbackResult. Theoretically, you could also in the error case make a usage of the message returned by GetCallbackResult.
- The client should be able parse the message in the front of encoded field validation, and to ignore the rest. Because this part of returned stream does not seem to be in place, it
could disappear in some future version of ASP.NET.
Hope this helps you.
Posted
Jun 11 2007, 06:50 PM
by
Damir Dobric