Showing posts with label AJAX. Show all posts
Showing posts with label AJAX. Show all posts

Monday, 13 September 2010

How to pass JSON arrays and other data types to an ASMX web service

Ah interoperability… great fun, great fun.

So jQuery is your new best friend and, along with JSON, there's nuthin' you can't do. The server side stuff is still there in the background and you've got some old school ASP.NET (.asmx) web services hanging around but DOM elements are otherwise flying all over the place, postbacks are just so passé, and even the marketing girls are mildly impressed at your skillz. You're branching out, shifting code and complexity from the server to the browser, and it's time to do some heavier data shunting. Here a few things to know about passing JSON data to an ASMX web service that may help you on your way…

JSON.stringify

Know it, use it, love it. It's part of the JSON2 library and you need it if you don't have it already. Use it to prepare (aka properly encode) your JSON data before sending it off to the big mean ol' web server:

data: {"days": JSON.stringify(["Mon", "Tues"])}

That will encode as &days=["Monday","Tuesday"]

Yeah, I know, it's another file to download but the guy who wrote JSON also wrote this and it can be merged and minified. I've tried writing my own mini-version as a function and while this works for simple strings, save yourself some time when it comes to arrays and the like and just use this sucker.

Arrays

Arrays seem trickier than they should… maybe I'm just a dumb guy—probably. Anyway, you can pass a JSON array to an .asmx web service without much work at all.

The client-side call listed above is everything you need to do from that end. On the server side, create yourself a new web service method with a List<string> parameter:

[WebMethod]
[ScriptMethod (UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public string ConsumeArray (List<string> days)
{…}

That's all there is to it. If you're not passing in strings, declare the List<> parameter with a type of object or something else. You can use .NET arrays in the web method signature as well if you really want (need) to.

Integers

When in doubt, stringify:

data: { "i": JSON.stringify(2) }

An int parameter on the web service end will handle this graciously.

Booleans

The good ol' boolean—a simple concept computer science has managed to bastardise like no other…

When in doubt, stringify:

data: { "b": jsonpEncode("true") }

Like the int parameter, a bool in your web method signature will take care of this.

A brief note: JSON, or rather jQuery's parseJSON function, is a particular beast and doesn't seem to know about anything other than the lower case true and false strings. If, for any reason, you ToString a bool in your .NET web service and try to pass it back, parseJSON will fail. If you forget to brush your teeth in the morning, parseJSON will fail.

Dates

Sorry, on my todo list ;-)

Tools

When working through this stuff, it pays to have Fiddler open to inspect the requests you're sending through and any error messages you're getting back. I find Fiddler sometimes breaks this stuff so try turning off the capture if you're getting weird errors; optionally, revert to Firebug (Firefox only, of course).

Fully decoding the data you sniff from a JSONP request passed along in the query string will require some additional tooling; in short, you'll want to decode the value using a free online tool like Opinionated Geek's URL decoder.

If you found this post helpful, please support my advertisers.

Monday, 5 July 2010

jquery.jsonp addresses issues with beforeSend and timeout

On the coat-tails of my previous post, I've come across the Google Code jquery-jsonp library and it's a saviour if you're working JSONP requests. Remember a JSONP request dynamically inserts a script tag into the DOM and doesn't use the same XMLHttpRequest as your typical AJAX request.

I ended up here because—much like beforeSend—the timeout parameter wasn't having any effect on my jsonp request: the request simply wouldn't time out despite the value supplied to this parameter.

In addition to supporting both beforeSend and timeout properties, jquery-jsonp adds some really nice caching support—both typical HTTP (aka "browser") caching and page-based caching that leverages the JavaScript VM's memory (apparently). Anyway it seems to work as advertised. Perhaps most importantly, the name of the callback can be changed.

A minified version of the code is available from Google Code and the documentation is concise and well-written with examples. 

Friday, 2 July 2010

.ajax beforeSend Doesn't Fire

I absolutely adore jQuery but there are some things that are just plain hard to do with the current version. One of those is cross-domain (JSONP) requests. No only is the setup convoluted but the requirements are exacting to arrive at a working solution for something that should be (?) reasonably simple. But I'll save the details for another time—for now, just know I'm building with jQuery and using JSONP to issue cross-domain requests.

Under the covers, that cross domain request is actually being issued by dynamically loading a new script tag in the DOM, even though everything's still handled through the $.ajax() function. It's workable, of course, but since there are no XMLHTTPRequests involved, the behaviour is apparently somewhat different. In my particular case, I was wiring up  'beforeSend and 'complete' event handlers to show and hide a spinner across the lifetime of the request; the 'complete' handler was firing fine but the 'beforeSend' handler wasn't firing at all.

A response by SLaks to a Stack Overflow post reminded me the request mechanism with JSONP is different and implied 'beforeSend' wouldn't work with this setup. His response instead suggested showing the spinner after the $.ajax call and this did the trick for me.