I have a simple client side webservice call that has a timeout and error handler defined:
TickUpdates.TickUpdate(tokenKey, SucceededCallback, FailedCallback, FailedCallback);
if I am not connected to the web, I get the following error. How can I capture this gracefully ?
[Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.status]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame ::http://localhost:45000/ScriptResource.axd?d=BSklnKRUU-3ZDmAWzNvjWRmHZJsJaTmhatiwatSzdV-n5b762_YnBv0exMpD6psRGreUx_ficbFeVQuAjTH012_sGHF6tKUojM03BRoiazs1&t=633084179322613693 :: Sys$Net$XMLHttpExecutor$get_statusCode :: line 4166" data: no]
http://localhost:45000/ScriptResource.axd?d=BSklnKRUU-3ZDmAWzNvjWRmHZJsJaTmhatiwatSzdV-n5b762_YnBv0exMpD6psRGreUx_ficbFeVQuAjTH012_sGHF6tKUojM03BRoiazs1&t=633084179322613693
Line 4166
In my case, it's happening because I'm trying to make a call to a PageMethod on a page that required authentication, but my authentication has timed out. In IE, I get an error with status 12030, but Netscape gives me the error above. This is a showstopper if I can't handle it gracefully via the FailedCallback handler.
Any ideas?
OK, so I figured out what's going on. In the Microsoft library, there's the following method:
function Sys$Net$XMLHttpExecutor$get_statusCode() {
/// <value type="Number"></value>
if (arguments.length !== 0) throw Error.parameterCount();
if (!this._responseAvailable) {
throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_statusCode'));
}
if (!this._xmlHttpRequest) {
throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler, 'get_statusCode'));
}
return this._xmlHttpRequest.status;
}
The problem with this is that Firefox throws an exception if the status isn't available, which is the case if you're offline, or, in my case, trying to access a PageMethod on a page requiring authentication after your logon has timed out. Throwing an exception is the W3 standard, as shown athttp://www.w3.org/TR/XMLHttpRequest/. Here is the related text...
status of type unsigned short, readonly
If the status attribute is not available an INVALID_STATE_ERR exception must be raised. It must be available when the state is receiving or loaded. When available, it must represent the HTTP status code (typically 200 for a successful request).
Its initial value must be 0.
So, what does this mean to us? It will require that Microsoft trap the exception thrown when the status isn't available, and then called the FailedCallback method so that we can handle it.
Here's my workaround. You can read the comments to know what I'm doing. With this fix to the get_statuscode method, I can then handle the 999 error code in my FailedCallback function. I hope this helps!
<script language="javascript">
//MS Ajax isn't handling getstatus exception, so i have to insert my own try/catch
//I'm doing it by creating a new prototype method... instead of rewriting the whole
//function, i'm simply taking the text of the current function, changing the name
//via replace, and changing the line accessing status to have try/catch wrapped around
//it. If the status call errors out, i'm returning error 999. You can return whatever you
//want.
//PS. I'm no javascript guru, so forgive me if I didn't use the most efficient
//code for creating a replacement function with the fixes.
//get the current function text
var funcText = Sys$Net$XMLHttpExecutor$get_statusCode.toString();
//our new function will have 'Patched_' appended to the start of the existing function
funcText = funcText.replace('Sys$Net$XMLHttpExecutor$get_statusCode', 'Patched_Sys$Net$XMLHttpExecutor$get_statusCode');
//replace status access with same line, except with try/catch block wrapped around it
funcText = funcText.replace('return this._xmlHttpRequest.status;', 'try {return this._xmlHttpRequest.status;} catch(e) {return 999;};');
//create new function using eval... to use funct = new Function or func = function() {...},
//I'd have to take the funcText and strip the function line and bracket from the beginning and the
//end. I could have done it by removing the first and last lines, but I did it this way instead.
eval(funcText);
//have the prototype method point to the new function instead of the old one
Sys.Net.XMLHttpExecutor.prototype.get_statusCode = Patched_Sys$Net$XMLHttpExecutor$get_statusCode;
</script>
I'm getting this error too in Firefox 1.0.3, but I'm not using any authentication. The oddities are:
1.) The error does not occur during the first asynchronous postback. The first one succeeds, but any subsequent async postbacks give the same error (pointing to the same Sys$Net$XMLHttpExecutor$get_statusCode() function).
2.) The error does not occur when I am using VS2005 in debug mode with a breakpoint at the codebehind event hander that handles the postback. When the code stops at the breakpoint, and I let it continue, the async postback succeeds.
Why would it work in debug mode with a breakpoint, but not in debug mode without breakpoints? Why would it succeed on the first postback, but not any subsequent ones?
This is just a weak opinion, but it sounds like a timing issue. I don't know why, but the pause that's introduced because of the breakpoint may enable it to complete, whereas without the pause it fails for some reason.
The issue I've documented definitely happens for reasons other than authentication. I hope I didn't give the impression that it's the only, or even primary, reason :).
John
FYI, MS has confirmed it's an issue, and is going to try to fix it in the Orcas release. In the meanwhile, they said the workaround I posted seems to be OK (although I'm sure they didn't have time to test it thoroughly - use at your own risk :)).
John
I thought of that, but inserting a System.Threading.Thread.Sleep(2000) call in the codebehind handler doesn't fix it.
I jumped the gun with this post anyway. As indicated athttp://ajax.asp.net/docs/BrowserCompatibilityForASPNETAJAX.aspx, UpdatePanels aren't officially supported for Firefox 1.0.x. Still, shouldn't Microsoft render in such a way that this browser uses synchronous postbacks instead of attempting asynchronous ones?
Then again, I'll have to chalk this one up to my system configuration. I just tried the same code using FF 1.0.3 on a different machine, and everything works as expected. Will have to try it in a production environment to see if the problem isn't coming from VS2005 and its embedded web server.
So it really is a confirmed issue? FYI I tried your fix. Whereas it did stop the error from popping up in the FF javascript console, it did not cause the second async postback to proceed. This is leading me more into thinking the problem was with my system configuration.
No comments:
Post a Comment