Monday, March 10, 2008

Working with Ajax.net - Javascript Error

I'm currently developing a project using Ajax.net and spent a few hours trying to figure out this bug that just started creaping in. When calling a specific WebService method, but not others, I would get this befuddling error. Then after I called that method and got the error, the other webservice methods would fail with the same error.

This is one of those things that scares me about some frameworks. Sure they help you speed up development when they are working but sometimes when they error out you are really screwed because they sometimes do not provide adequate error messages to help you resolve your problem.

This is the first project that I have called a webservice from javascript, and the first time I had used the ScriptService attribute on a webservice and I was impressed with the ease of how it worked. Previously I had sort of rolled my own httpRequests against blank asp pages, so I really liked the work I saved using ajax.net instead.

But then, after coming back to work on a Monday, I had started to get this error:
Sys.ArgumentTypeException: Object of type 'String' cannot be converted to type 'Function'. Parameter name: onFailure

According to FireBug, It was occuring on this line:
{name: "userContext", mayBeNull: true, optional: true}
inside the function prototype
Function._validateParams in the Sys$Net$WebServiceProxy$_invoke function of ScriptResource.axd. This is all generated code that I have absolutely no control over.

I spent several frustrated hours googling the error message and trying to figure out what was wrong.
Other people were getting the error but none really described my problem or resolved the issue. We had had some svn troubles and I thought it might have something to do with that. I wondered it maybe it had never worked on that computer because I had done a lot of it on my laptop. But after firing up the laptop, it was having the same error too. I tried changing the parameters, adding one or two bogus strings parameters to it. But nothing would give me a clue as to what was wrong.

So after creating a new function and copying things over to it and seeing it work just fine inside another method it finally hit me like a ton of bricks. The error message that I thought was telling me nothing was telling me everything. Within that block of code I had defined a string variable with the same name as my error handling method, both of them were called "error". When I tried to use error as my OnFailure function parameter, it was using the string instead.

Once that branch of code was executed, "error" was defined as a string instead of a method, because javascript doesn't have scope, and every other method that used the "error" function was now using a string instead.

My computer science professor would probably be ashamed. But I suppose a developer with 9 years of experience needs to be humbled every now and then with a freshman mistake.