Blog Archives

Improving jQuery’s JSON performance and security

When you’re working with JSON, performance and security are often opposing, yet equally important concerns. One of these areas of contention is handling the JSON strings returned by a server. Most JavaScript libraries do a great job of abstracting away the details, but the underlying process has long been a frustrating exercise in compromise.

On one hand, eval() is the fastest widely available method, but it is not safe.

On the other hand, textual JSON parsers written in JavaScript may be much safer, but are dramatically slower. In client-side situations, where milliseconds count, such a large performance overhead is typically too prohibitive to accept.

Recently, an exciting new alternative has emerged: browser-native JSON parsing. Integrating JSON parsing as part of the browser’s implementation of JavaScript allows for using the more secure parsing method, and even provides performance faster than eval() offers.

To take advantage of that, this post will show you how to detect whether or not a browser supports native JSON parsing, and how to force jQuery to use browser-native parsing in its $.ajax calls when it is available.

Native JSON parsing in the browser

Previously known as ECMAScript 3.1, ECMAScript “Fifth Edition” (the specification that JavaScript implements) formally codifies a native JSON parsing feature. The spec’s API exactly mirrors that of Crockford’s implementations of JSON.parse and JSON.stringify in json2.js, easing the transition to browser-native functionality.

This native JSON parsing brings marked improvements in terms of both security and performance. Not only does the native routine use textual parsing to avoid the risk of executing malicious code embedded within JSON, but it is also fast.

At the time of this writing, three major browsers already include support for native JSON parsing: IE8, Firefox 3.5, and Chrome 3.

Safari 4 does not currently support the standard, but its underlying engine (WebKit) has recently implemented it. Hopefully the feature will make its way to Safari soon.

Detecting native JSON support

Determining whether or not native JSON parsing is available within a given browser is the first problem we need to solve. To do this, we ultimately need to know if the JSON.parse function is defined.

We can’t test for JSON.parse directly because attempting to reference it will throw a JavaScript error if the underlying JSON object doesn’t exist. So, first we need to inspect the type of that underlying object itself:

if (typeof(JSON) === 'object') {
  // native JSON may be available.
}

If we find that the JSON object does exist, it’s likely that native JSON parsing is available. However, it’s a best to double check the JSON.parse function as well:

if (typeof(JSON.parse) === 'function') {
  // native JSON parsing is available.
}

Because JavaScript performs short-circuit evaluation, it’s safe to clean this up by combining both tests in a single conditional, as long as they’re in this order:

if (typeof(JSON) === 'object' &&
    typeof(JSON.parse) === 'function') {
  // Native JSON parsing is available.
}

Curious whether your browser supports native JSON parsing? Using the JavaScript above, I have determined that:

You appear to have JavaScript disabled or are reading this in an RSS reader. In order to view the status of your browser’s native JSON capability, please view this post in a browser with JavaScript enabled.

Extending jQuery to use native JSON parsing

In my previous post, I demonstrated how to use jQuery’s dataFilter to transform a JSON response before it is returned to the $.ajax() success handler. In the process, we also preempted jQuery’s default method for deserializing JSON data.

The focus at that time was implementing the same method for JSON parsing that jQuery uses by default, so eval() was still used. However, we can also use the same dataFilter mechanism to force browser-native JSON parsing instead.

Using our JSON parsing detection code and a dataFilter callback, upgrading jQuery to use browser-native parsing is simple:

$.ajax({
  // Your usual $.ajax() URL, data, dataType, etc.
  dataFilter: function(data) {
    if (typeof (JSON) !== 'undefined' &&
        typeof (JSON.parse) === 'function')
      return JSON.parse(data);
    else
      return eval('(' + data + ')');
  }
});

Because jQuery only attempts to deserialize JSON responses if their type is string, and because the dataFilter callback executes before jQuery would normally perform that deserialization, this technique preempts jQuery’s JSON evaluation completely. In the worst case, it will simply revert back to the same eval() method that jQuery internally uses by default anyway.

Note: It’s important to keep in mind that the dataFilter will run regardless of what type is actually returned from the server. You should only use this when you’re sure that you’re receiving a JSON string.

Conclusion

If you’ve been paying close attention to jQuery’s ongoing development, you may already know that jQuery 1.3.3 will provide functionality very similar to what I’ve shown you. I decided to go ahead and write this post anyway for a few reasons:

  • You can use this today, without waiting for jQuery 1.3.3.
  • You can use this in previous versions of jQuery, if upgrading isn’t feasible for you (as is often the case with plugins dependent on older versions).
  • If you use my technique for isolating your code from ASP.NET AJAX’s “.d”, you will still need a method for deserializing JSON in the dataFilter.

Speaking of that last point, if you’re using jQuery with ASP.NET AJAX services, be sure to watch out for the next post in this (accidental) series. There is at least one more productive step left in improving this workflow that I have been using in my projects and want to share with you soon.

###

Originally posted at Encosia. If you’re reading this elsewhere, come on over and see the original.

Improving jQuery’s JSON performance and security

Never worry about ASP.NET AJAX’s .d again

When I recently received this message from a frustrated reader:

After hours and hours of slamming my head into the desk it turns out it was the darn "d" in the response. My home computer is on .NET 2.0 and my work computer is on 3.5. Jimminie Christmas!

I realized that the “.d” introduced in ASP.NET AJAX 3.5’s JSON responses is still all too common a stumbling block when calling ASP.NET AJAX services through a library such as jQuery. In fact, with jQuery’s popularity among ASP.NET developers on the rise, this appears to have become an even more frequent problem.

Since a lot of people are having trouble with it, I want to share one method you can use to completely isolate your code from the problem. If you bake this into an $.ajax() code snippet or otherwise use it as a template for calling ASP.NET AJAX services in jQuery, you should never have to think or worry about the “.d” again.

In this post, I will show you how to detect the “.d” and how you can completely isolate your $.ajax success handler from it.

“.d” what?

If you aren’t familiar with the “.d” I’m referring to, it is simply a security feature that Microsoft added in ASP.NET 3.5’s version of ASP.NET AJAX. By encapsulating the JSON response within a parent object, the framework helps protect against a particularly nasty XSS vulnerability.

Before ASP.NET 3.5, “ScriptServices” and page methods returned their data at the top level of the JSON response, like this:

2.0 JSON Response in Firebug

In ASP.NET 3.5 and later, the same server-side code returns this:

3.5 JSON Response in Firebug

For more information about the change and why the change is a good one, be sure to see my earlier post: A breaking change between versions of ASP.NET AJAX.

However, what my previous post lacks is a solution for mitigating the inconsistency entirely. Using different client-side code against 2.0 and 3.5 based services is workable, but far from ideal. Wouldn’t it be nicer to not have to worry about it?

Determining whether or not the “.d” is there

In order to isolate ourselves from the “.d”, we first need a reliable way to test for its presence. Though JavaScript provides several methods for determining this, I suggest hasOwnProperty, as recommended by Douglas Crockford.

By using hasOwnProperty, your code is protected against unexpected changes to an object’s prototype chain. Though it is an unlikely problem to encounter, it’s always best to code defensively in JavaScript. The browser is a hostile environment!

Using hasOwnProperty to test for “.d”, you might end up with something like this:

$.ajax({
  type: "POST",
  url: "WebService.asmx/MethodName",
  data: "{}",
  contentType: "application/json; charset=utf-8",
  dataType:"json",
  success: function(msg) {
    if (msg.hasOwnProperty("d"))
      // Leave the .d behind and pass the rest of 
      //  the JSON object forward.
      DoSomething(msg.d);
    else
      // No .d; no transformation necessary.
      DoSomething(msg);
  }
});
 
function DoSomething(msg) {
  // Do something with the response data here.
  //  Expect it to consistently have no .d.
}

This code will perform identically against any version of ASP.NET AJAX.

Unfortunately, this might still get in your way. You may not always want to use the response in a call to another function, and you’ll have to remember the conditional every time you write a success handler.

Don’t make me think

I prefer a solution that doesn’t touch the success handler at all. Then, you’re free to integrate the “.d” handling into a generic $.ajax code snippet in Visual Studio and/or easily copy-paste it between files without modification.

Luckily, jQuery provides a mechanism that allows us to do just that: dataFilter.

The dataFilter parameter to $.ajax allows you to arbitrarily transform a response just before the success handler fires. Specifically tailored to this sort of situation, it passes response data into a callback function, captures the return value of that callback, and then passes the modified data into your success handler.

Hence, you can forever stop worrying about that pesky “.d” like this:

$.ajax({
  type: "POST",
  url: "WebService.asmx/MethodName",
  data: "{}",
  contentType: "application/json; charset=utf-8",
  dataFilter: function(data) {
    // This boils the response string down 
    //  into a proper JavaScirpt Object().
    var msg = eval('(' + data + ')');
 
    // If the response has a ".d" top-level property,
    //  return what's below that instead.
    if (msg.hasOwnProperty('d'))
      return msg.d;
    else
      return msg;
  },
  success: function(msg) {
    // This will now output the same thing 
    //  across any current version of .NET.
    console.log(msg.foo);
  }
});

Now, regardless which of these JSON forms the server returns:

// ASP.NET 2.0 with the ASP.NET AJAX Extensions installed.
{'foo':'bar'}
 
// ASP.NET 3.5 and 4.0.
{'d':{'foo':'bar'}}

Your success handler will simply receive this consistent JSON object every time:

{'foo':'bar'}

dataType: none of your business

It’s important to note the removal of the dataType parameter in the $.ajax() code above. This is required in order to prevent a double-eval of service responses containing only a single string.

Internally, jQuery uses a combination of the dataType parameter and the implicit type the response. If the dataType is "json" and typeof(response) is “string”, then jQuery uses eval() to deserialize the response.

In the example above, manually deserializing the response in dataFilter results in it being of type Object, jQuery leaves it alone, and our dataFilter’d object makes its way back to the success callback either way.

However, if the dataType is set to “json” and the “.d” sanitized response happens to be of JavaScript type “string”, jQuery will assume that it is a JSON response from the server and still needs to be deserialized. That will throw an error at best.

The solution is to simply drop the dataType parameter from the $.ajax() call. It is only needed for purposes of instructing jQuery how to deserialize the response, and we’re handling that ourselves now.

Thanks to Brett for pointing this out.

Wait, isn’t eval() supposed to be evil?

If the eval() usage gives you pause, don’t worry. For now (as of jQuery 1.3.2), this is the same mechanism that jQuery uses to deserialize JSON too. Though eval() is potentially evil, it is still a necessary evil in many browsers.

In my next post, I’ll show you how to modify this to leverage a native browser implementation of JSON.parse instead of eval(), available in some newer browsers.

That post is available now: Improving jQuery’s JSON performance and security.

###

Originally posted at Encosia. If you’re reading this elsewhere, come on over and see the original.

Never worry about ASP.NET AJAX’s .d again

Automatically minify and combine JavaScript in Visual Studio

As you begin developing more complex client-side functionality, managing the size and shape of your JavaScript includes becomes a key concern. It’s all too easy to accidentally end up with hundreds of kilobytes of JavaScript spread across many separate HTTP requests, significantly slowing down your initial page loads.

To combat this, it’s important to combine and compress your JavaScript. While there are useful standalone tools and HttpHandler based solutions to the problem already, none of them work quite how I prefer. Instead, I’m going to show you my dead-simple method for automatically compressing and combining script includes.

To accomplish that in this post, we will select a compression utility, learn how to use it at the command line, explore a useful automation feature in Visual Studio, and apply that to keep scripts combined and compressed with no ongoing effort.

Selecting a JavaScript compression tool

The first thing we’ll need is a utility to compress our JavaScript. There are many utilities available, ranging from YUI Compressor to Dean Edwards’ Packer, each with its own strengths and weaknesses.

YUI Compressor is powerful, but requires a Java runtime be available during the build process. Packer is popular for its Base62 encoding mode, however that form of compression carries a non-trivial performance tax on the client-side.

In terms of simplicity, it’s hard to beat Douglas Crockford’s JSMin. It requires no command line options, no runtimes or frameworks, and accepts input directly from standard input (which will be useful for us later).

One common concern about JSMin is that it outputs less compact code than YUI Compressor and Packer on their most aggressive settings. However, this is a bit of a red herring. When gzipped, the result of all three boil down to almost exactly the same size across the wire. Since you should always serve your JavaScript with gzip compression at the HTTP level, this initial “disadvantage” is moot.

Using JSMin from the command line

Using JSMin is very straightforward. For example, say we have the following, well-commented JavaScript and want to minify it:

// how many times shall we loop? 
var foo = 10;
 
// what message should we use? 
var bar = 'Encosia';
 
// annoy our user with O(foo) alerts! 
for (var i = 0; i < foo; i++) {
  alert(bar);
}

Assuming that JavaScript is in a file called AlertLoop.js, this command line usage of JSMin will minify it and output it to the console:

jsmin < AlertLoop.js

jsmin-stdin

What this does is run jsmin and feed the contents of AlertLoop.js into standard input. It’s the same as if you had run jsmin and then typed all that JavaScript on the command line.

Similarly, this usage does the trick if you want to redirect that output to a file:

jsmin < AlertLoop.js > AlertLoop.min.js

jsmin-to-file

The minified output is less than half the size of the original. Not bad!

Note: If you’re wondering about the upper ASCII characters preceding the minified script, they’re nothing to be concerned about. Because I had created AlertLoop.js in Visual Studio, it was saved as UTF-8 by default and those characters are the UTF BOM (thanks to Oleg, Sugendran, and Bart for clarification).

Set up project directories

project-layoutBefore we get to the next steps, we need to define a structure for our project. The one shown to the right works for simple projects.

Within the website project, the important takeaway is that the JavaScript files to be compressed are all in the same directory and named with a *.debug.js pattern.

Outside of the website, notice the “tools” directory which contains a copy of JSMin. I think we can all agree that executables should not be included within a website project if possible. That would just be begging for trouble.

However, I do suggest including an external tools directory and JSMin executable in your project’s source control. You never want to create a scenario where someone can’t perform a checkout and then a successful build immediately afterward.

Automation: Visual Studio earns its keep

To automate script compression as part of the build process, I suggest using a build event. There are perfectly legitimate alternatives, but I prefer having a tangible file sitting on disk and having that compression process automated. So, “building” the minified JavaScript include(s) as part of the build process makes the most sense to me.

Build events may sound complicated, but they aren’t at all. Build events are simply a mechanism for executing command line code before and/or after your project is compiled.

For our purposes, a post-build event is perfect. Additionally, we can specify that it should only run the build event if the project builds successfully. That way we avoid wasting unnecessary time on minifying the JavaScript when there are build errors.

Setting up a build event in Visual Studio

To add build events, right-click on your project and choose properties. In the properties page that opens, click on the “Build Events” tab to the left. You’ll be presented with something similar to this:

project-properties

Note: If you’re using Visual Basic, there will be no build events tab in the project properties. Instead, look for a build events button on the “Build” tab, which allows access the same functionality.

You can type commands directly in the post-build field if you want, but clicking the “Edit Post-build” button provides a better editing interface:

post-build-events

The interface’s macro list is especially useful. In particular, the ProjectDir macro will be handy for what we’re doing. $(ProjectDir) placed anywhere in a build event will be replaced with the actual project path, including a trailing backslash.

For example, we can use it to execute JSMin.exe in the hierarchy described above:

$(ProjectDir)..toolsjsmin.exe

Or, reference that same project’s js directory:

$(ProjectDir)js

Putting it all together: Minify a single file

Now that we’ve covered how to use JSMin at the command line and how to execute command line scripts as part of Visual Studio builds, putting it all together is easy.

For example, to minify default.debug.js, this post-build event will do the trick:

"$(ProjectDir)..toolsjsmin" <
"$(ProjectDir)jsdefault.debug.js" >
"$(ProjectDir)jsdefault.min.js"

(The line breaks are for readability here. The command in your actual build event must not contain them, or it will be interpreted as separate commands and fail.)

The quotes are important, in case $(ProjectDir) happens to include directories with spaces in their names. Since you never know where this project may eventually be built at, it’s best to always use the quotes.

*Really* putting it together: Combine files

I did promise more than just compression in the post’s title. Combining scripts is just as important as compression, if not more so. Since JSMin takes its input from stdin, it’s easy to roll scripts together for minification into a single result:

type "$(ProjectDir)js*.debug.js" |
"$(ProjectDir)..toolsjsmin" >
"$(ProjectDir)jsscript-bundle.min.js"

This build event would combine all of our *.debug.js scripts, minify the combined script bundle, and then output it in a new file named script-bundle.min.js.

This is great if you want to combine your most commonly used jQuery plugins into a single payload, for example. A reduction in HTTP requests usually provides a nice improvement in performance. This is especially true when you’re dealing with JavaScript, because the browser blocks while script references load.

Dealing with dependencies

Cross-dependencies between scripts is one issue that requires extra consideration when combining. Just the same as ordering script includes incorrectly, bundling scripts together in the wrong order may cause them to fail.

One relatively easy way to handle this is to give your scripts prefixes to force the correct order. For example, the source sample below includes this set of JavaScript files:

jQuery-1.3.2.debug.js
jQuery-jtemplates.debug.js
default.debug.js

Combining these and referencing the result will fail, because default.debug.js is sorted ahead both jQuery and the plugin by default. Since default.debug.js depends on both of those, this is a big problem. To fix this, rename the files with prefixes:

01-jQuery.debug.js
05-jQuery-jtemplates.debug.js
10-default.debug.js

Now it will work perfectly.

Any system of alphanumeric prefixes will work, but if you use a numeric system, be sure to pad the numbers with leading zeroes. Otherwise, the default sort ordering may catch you off guard (e.g. 2-file.js sorts ahead of 11-file.js through 19-file.js).

To debug, or not to debug

Now that we have the minification process under control, one final issue to address is how to keep this from complicating our development workflow.

While editing these scripts, we certainly don’t want to be forced to recompile every time we make a change to the JavaScript. After all, one of the nice things about JavaScript is that it doesn’t require precompilation. Even worse, using a JavaScript debugger against minified files is a nightmare I wouldn’t recommend to anyone.

The easiest way I know of to ensure that the correct scripts are emitted for both scenarios is to check the IsDebuggingEnabled property of the HttpContext:

<head>
<% if (HttpContext.Current.IsDebuggingEnabled) { %>
  <script type="text/javascript" src="js/01-jquery-1.3.2.debug.js"></script>
  <script type="text/javascript" src="js/05-jquery-jtemplates.debug.js"></script>
  <script type="text/javascript" src="js/10-default.debug.js"></script>
<% } else { %>
  <script type="text/javascript" src="js/js-bundle.min.js"></script>
<% } %>
</head>

When the web.config’s compilation mode is set to debug, the *.debug.js versions of the files are referenced, and the auto-minified bundle otherwise. Now we have the best of both worlds.

Conclusion

I hope you’ll find that this technique is a good compromise between the tedium of using manual minification tools and the overwrought complexity of setting up some of the more “enterprisey” automation solutions.

One not-so-obvious benefit that I’ve noticed stems from minification’s automatic comment stripping. Without worry about your comments burdening the size of the client-side payload or being distributed across the Internet, you’re more likely to comment your JavaScript well. Dealing with a dynamic language, sans-compiler, I find that comments are often crucial to maintainability.

This is one of those problems with quite a few perfectly legitimate solutions. What do you think of this solution? How do you normally handle this?

Get the source

For demonstration, I took my jQuery client-side repeater example and applied this technique. Having several JavaScript includes (one that’s full of comments), it’s a perfect candidate for combining and compression.

One particular thing to notice in this example is the use of numeric prefixes to order the JavaScript includes, as mentioned earlier. This naming scheme is crucial when dealing with interdependent scripts. If the scripts are combined in the wrong order, your functionality will break just the same as if you had used script reference tags in the wrong order.

Download Source: jsmin-build.zip

###

Originally posted at Encosia. If you’re reading this elsewhere, come on over and see the original.

Automatically minify and combine JavaScript in Visual Studio

What ASP.NET developers should know about jQuery

As much as I enjoyed attending MIX09 this year, it wasn’t a difficult decision when Karsten asked me to write an article for the MIX Online site.

Reading this here, there’s a good chance the article is targeted below the amount of jQuery expertise you already have. However, it’s been brought to my attention that some readers have found it useful for sending to their more JavaScript-phobic coworkers.

So, I decided that it’s worth mentioning here after all:

It’s hard to believe that JavaScript is already well over a decade old. Often relegated to marginal tasks in its early years, JavaScript has grown to become a pillar of modern web development. With the current popularity of DHTML and AJAX, it can be difficult to find a site that doesn’t use JavaScript anymore. One of the driving forces behind JavaScript’s newfound popularity is a proliferation of JavaScript frameworks, such as jQuery.

 

Why?

Click here to continue reading this article on the MIX Online site »

###

Originally posted at Encosia. If you’re reading this elsewhere, come on over and see the original.

What ASP.NET developers should know about jQuery

How I handle JSON dates returned by ASP.NET AJAX

A calendar

The problem of how to handle dates in JSON is one of the more troublesome issues that may arise when directly calling ASP.NET AJAX web services and page methods.

Unlike every other data type in the language, JavaScript offers no declarative method for expressing a Date. Consequently, embedding them within JSON requires a bit of fancy footwork. Since the question of how I handle this problem is something asked often in emails and in comments on other posts here, I want to address the topic with its own post.

To that end, I will attempt to explain what exactly the problem is with dates in JSON, how ASP.NET AJAX solves it, and my alternative solution that I believe is easier and works just as well in most cases.

What’s the problem?

The fundamental problem is that JavaScript does not provide a way to declaratively express Date objects. You may previously have seen this described as (the lack of) a Date literal.

What are literals? To illustrate, these are literals for several other data types:

// String
'foo';
 
// Number
3.14;
 
// Boolean
true;
 
// Array
[1, 2, 3, 5, 7];
 
// Object
{ pi: 3.14, phi: 1.62 };

Unfortunately, when it comes to dates, the lack of a literal means that the only way to create one is by explicitly initializing a Date object:

// Correct.
new Date('4/26/09');
 
// Correct (the month is 0 indexed, hence the 3).
new Date(2009, 3, 26);
 
// Incorrect. This is a string, not a Date.
'4/26/09';

While this limitation is fine when writing client-side JavaScript code, it leaves us without a good way to transmit dates within JSON objects.

How ASP.NET AJAX handles it

While the lack of a date literal is a problem, it’s certainly not without solution.

In fact, ASP.NET AJAX already handles this if you’re using MicrosoftAjax.js to call your services. You may not have even noticed as server-side DateTime values are transparently converted into JavaScript Date objects on the client-side.

For example, consider this web service:

[System.Web.Script.Services.ScriptService]
public class DateService : System.Web.Services.WebService
{
  [WebMethod]
  public DateTime GetDate()
  {
    return new DateTime(2009, 4, 26);
  }
}

If you consume that web service with jQuery (or any method that circumvents the ScriptManager), you’ll find that ASP.NET AJAX serializes the DateTime as an escaped JavaScript Date initializer:

{"d":"/Date(1240718400000)/"}

Note: If you’re unsure about why the “d” is there, be sure to see my recent post about this security feature which was added in ASP.NET 3.5.

On the client-side, MicrosoftAjax.js uses a regular expression to isolate any Date constructors and then eval() to initialize Date objects. The end result is that proper JavaScript Date objects are instantiated for every DateTime value returned.

However, if you’re not using MicrosoftAjax.js (i.e. the ScriptManager) to call your services, you’ve got a bit of a mess to decode. You can use regex machinations to work around the problem, but is that really necessary?

How I handle it

Consider why you want to send a DateTime to the client-side to begin with. Most often, you’re displaying a string representation of it and have no need for the proper JavaScript Date object.

What’s more, if you end up with a JavaScript Date object, you’ll probably use additional code or a JavaScript library to display it in a user-friendly format.

As much as I appreciate a clever workaround, I’d much rather avoid the problem completely. Rather than jump through all of these hoops to instantiate a JavaScript Date object on the client-side and then format it, I suggest simply returning a formatted string.

For example, we might modify the previous example like so:

[System.Web.Script.Services.ScriptService]
public class DateService : System.Web.Services.WebService
{
  [WebMethod]
  public string GetDate()
  {
    return new DateTime(2009, 4, 26).ToLongDateString();
  }
}

Now, calling the service will return this JSON:

{"d":"Sunday, April 26, 2009"}

No more regular expressions. No more JavaScript Date objects. No more worrying about formatting the data on the client-side.

Even better, no functionality is lost. If we need to instantiate Dates, we still can.

Still want Dates?

Even if you do end up needing JavaScript Date objects, DateTime strings are sufficient for instantiating them. JavaScript’s Date constructor is very flexible:

// ASP.NET AJAX form
var foo = new Date(1240718400000);
 
// DateTime.ToLongDateString() form
var bar = new Date('Sunday, April 26, 2009');
 
// DateTime.ToShortDateString() form
var baz = new Date('4/26/2009');
 
// true!
foo === bar === baz;

By delaying string-to-Date conversions until truly necessary, we save effort on the server- and client-side. Not only that, but we have the option of retaining both the formatted string and the JavaScript Date to use as desired.

The best of both worlds.

###

Originally posted at Encosia. If you’re reading this elsewhere, come on over and see the original.

How I handle JSON dates returned by ASP.NET AJAX

Using complex types to make calling services less… complex

So far, my examples of using jQuery to interact with ASP.NET AJAX services have avoided passing complex data to the server during the request. This has been intentional, because I didn’t want to over-complicate the examples.

For primarily read-only scenarios, like the RSS reader examples, passing just a few simple values to the service is often all you need. However, this scalar approach quickly becomes untenable when making real-world service calls.

In this post, I’m going to show you how passing complex types to the server helps alleviate complexity, how json2.js and a data transfer object (DTO) facilitates this, and how to use jQuery to very easily build the DTO.

Setting the stage

Let’s say that we want to improve the performance of a data entry application used to add Person records to a database. The original version was developed quickly using an UpdatePanel, but performs poorly. Not wanting the Person-data-entry-department to spend more time waiting than they do typing, we must find a way to improve the application’s performance.

Having done some research, we might decide that replacing the UpdatePanel with jQuery and a web service would be a great way to speed things up.

A foundation and a facade

The properties of the existing Person class could be as simple as this:

public class Person
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string Address { get; set; }
  public string City { get; set; }
  public string State { get; set; }
  public string Zip { get; set; }
 
  public void Add()
  {
    // Magic happens here.
  }
}

The original entry form probably used TextBox controls, but that will no longer be necessary. Regular HTML input elements carry less overhead and ensure that we don’t have to worry about ClientID issues:

<label for="FirstName">First Name:</label>
<input type="text" id="FirstName" />
 
<label for="LastName">Last Name:</label>
<input type="text" id="LastName" />
 
<label for="Address">Address:</label>
<input type="text" id="Address" />
 
<label for="City">City:</label>
<input type="text" id="City" />
 
<label for="State">State:</label>
<input type="text" id="State" />
 
<label for="Zip">Zip:</label>
<input type="text" id="Zip" />
 
<input type="button" id="Save" value="Save" />

Note that the input elements have IDs matching the corresponding Person property. This will help us implement an improvement to our client-side code later on.

One way not to do it

Now that we’ve had a look at the front and back ends, it’s time to connect them together with a web service. One unfortunate anti-pattern that often emerges in this situation is a service method with too many parameters:

[WebMethod]
public void AddPerson(string FirstName, string LastName,
                      string Address, string City,
                      string State, string Zip)
{
  Person newPerson = new Person();
 
  newPerson.FirstName = FirstName;
  newPerson.LastName = LastName;
  newPerson.Address = Address;
  newPerson.City = City;
  newPerson.State = State;
  newPerson.Zip = Zip;
 
  newPerson.Add();
}

Not only do we have to manually keep that method’s parameter list in sync with the Person class, but we also have to maintain the pointless object initialization code.

Calling the service on the client-side is just as messy too:

$.ajax({
  type: "POST",
  contentType: "application/json; charset=utf-8",
  url: "PersonService.asmx/AddPerson",
  data: "{'FirstName':'" + $("#FirstName").val() + "', "
       + "'LastName':'" + $("#LastName").val() + "',"
       + "'Address':'" + $("#Address").val() + "',"
       + "'City':'" + $("#City").val() + "',"
       + "'State':'" + $("#State").val() + "',"
       + "'Zip':'" + $("#Zip").val() + "'}",
  dataType: "json"
});

As ugly as it is, that will work and be much faster than anything we could possibly implement in an UpdatePanel. It would also be a nightmare to maintain.

Let’s continue improving this until it’s something we can be proud of.

Things can only get better

A good first improvement is to refactor the web service to get rid of the parameter list and redundant object initialization.

Most examples (including my own) never go beyond passing a string, integer, or maybe an array, but that only scratches the surface of what’s possible. An underutilized feature of ASP.NET AJAX “ScriptService” methods is that they can accept complex types as parameters and parse those parameters from JSON.

Leveraging this, we can dramatically simplify the web service:

[WebMethod]
public void AddPerson(Person NewPerson)
{
  NewPerson.Add();
}

Unfortunately, calling this method on the client-side is just as messy as ever:

$.ajax({
  type: "POST",
  contentType: "application/json; charset=utf-8",
  url: "PersonService.asmx/AddPerson",
  data: "{'NewPerson': {'FirstName':'" + $("#FirstName").val() + "',"
                     + "'LastName':'" + $("#LastName").val() + "',"
                     + "'Address':'" + $("#Address").val() + "',"
                     + "'City':'" + $("#City").val() + "',"
                     + "'State':'" + $("#State").val() + "',"
                     + "'Zip':'" + $("#Zip").val() + "'}}",
  dataType: "json"
});

That’s about the same as before. However, instead of sending a flat group of input field values, now we’re sending a JSON object corresponding to the Person class.

In other words, that declarative JSON data string is equivalent to this JavaScript:

var NewPerson = new Object();
 
NewPerson.FirstName = $("#FirstName").val();
NewPerson.LastName = $("#LastName").val();
NewPerson.Address = $("#Address").val();
NewPerson.City = $("#City").val();
NewPerson.State = $("#State").val();
NewPerson.Zip = $("#Zip").val();

ASP.NET AJAX seamlessly translates the JSON string into a new instance of our Person class and passes that object into the service method. It works exactly as you’d expect, which is almost too good to be true!

Cleaning up the client-side

The best way to improve the client-side situation is to abandon our manual JSON serialization in the $.ajax() call. It works well enough for a couple parameters, but has devolved into a ball of mud as the parameter count increased.

Douglas Crockford’s json2.js contains a stringify function which is exactly what we need. Stringify() accepts a JSON object and returns the same type of string that we’re manually concatenating together right now.

Using json2.js, our previous client-side code can be refactored to this:

// Initialize the object, before adding data to it.
var NewPerson = new Object();
 
NewPerson.FirstName = $("#FirstName").val();
NewPerson.LastName = $("#LastName").val();
NewPerson.Address = $("#Address").val();
NewPerson.City = $("#City").val();
NewPerson.State = $("#State").val();
NewPerson.Zip = $("#Zip").val();
 
$.ajax({
  type: "POST",
  contentType: "application/json; charset=utf-8",
  url: "PersonService.asmx/AddPerson",
  data: "{'NewPerson':" + JSON.stringify(NewPerson) + "}",
  dataType: "json"
});

It’s still a fair amount of code, but it’s much cleaner. If you dropped this in my lap and asked me to maintain it, we wouldn’t have a problem.

Using a data transfer object

Adding json2.js and its stringify functionality made our code significantly more readable, but we can do better. There’s still a bit of manual JSON string building in the $.ajax() call, which would be nice to avoid.

Since we already have JSON.stringify() at our disposal, we can build and stringify a JSON object to represent the entire request’s data instead of just the form data:

// Initialize the object, before adding data to it.
//  { } is declarative shorthand for new Object().
var NewPerson = { };
 
NewPerson.FirstName = $("#FirstName").val();
NewPerson.LastName = $("#LastName").val();
NewPerson.Address = $("#Address").val();
NewPerson.City = $("#City").val();
NewPerson.State = $("#State").val();
NewPerson.Zip = $("#Zip").val();
 
// Create a data transfer object (DTO) with the proper structure.
var DTO = { 'NewPerson' : NewPerson };
 
$.ajax({
  type: "POST",
  contentType: "application/json; charset=utf-8",
  url: "PersonService.asmx/AddPerson",
  data: JSON.stringify(DTO),
  dataType: "json"
});

By creating a data transfer object (often referred to as a DTO), we’ve completely eliminated all manual JSON string building.

Even though it’s a small change, it feels quite a bit cleaner doesn’t it?

Bonus: jQuery makes everything better

Using the DTO makes sending the form data clean, but we’re still stuck with the unnecessary chore of maintaining the NewPerson initialization block. jQuery is perfectly suited to solving this problem:

// Initialize the object, before adding data to it.
//  { } is declarative shorthand for new Object().
var NewPerson = { };
 
// Iterate over all the text fields and build an
//  object with their values as named properties.
$('input[type=text]').each(function() {
  // Ex: NewPerson['FirstName'] = $('#FirstName').val();
  NewPerson[this.id] = this.value;
});
 
// Create a data transfer object (DTO) with the proper structure.
var DTO = { 'NewPerson' : NewPerson };
 
$.ajax({
  type: "POST",
  contentType: "application/json; charset=utf-8",
  url: "PersonService.asmx/AddPerson",
  data: JSON.stringify(DTO),
  dataType: "json"
});

Using jQuery.each() to iterate over the fields and build our client-side object is a nice improvement. Even in this simple example, it cuts down on the amount of JavaScript we have to write and maintain. In real-world scenarios where your objects have dozens of properties, this will save you a lot of time (and typos).

More important than saving a few keystrokes, we’ve got one less place to worry about updating if the Person class changes in the future. We can modify the Person class, update the entry form accordingly, and this will continue working.

Conclusion

We have solidly accomplished the goal of refactoring this until it’s something we can be proud of. There’s always room for improvement, but this will serve as a great start for writing robust, maintainable client-side service calls.

Death by a thousand dependencies: When I first started experimenting with this stringified DTO pattern, I was reluctant to take on the json2.js dependency. However, it’s tiny when minified, has no dependencies of its own, and is ideal for rolling into another combined script. Its dependable functionality is well worth a few kilobytes.

A great thing about committing to the JSON.stringify usage is that web browsers are beginning to natively support it. So, at some point in the future, you’ll actually be able to drop the json2.js dependency and this method will still work (faster).

DTOs: If your server-side situation is more complex than this example (and it probably is), don’t be afraid to use a throw-away DTO class as the service method parameter.

For example, our Person class could also have been a PersonDTO class, specifically intended to take these form submissions and merge them into a more complicated domain.

Source

jQuery DTO source download

###

Originally posted at Encosia. If you’re reading this elsewhere, come on over and see the original.

Using complex types to make calling services less… complex

$(document).ready() and pageLoad() are not the same!

Recently, I’ve attended several presentations in which ASP.NET AJAX’s pageLoad() shortcut is demonstrated as interchangeable with jQuery’s $(document).ready() event. The suggestion that both methods are equivalent actually appears to be true in simple demos, but is not the case and is certain to lead to later confusion.

While they seem similar on the surface, $(document).ready() and pageLoad() are very different behind the scenes. Determining the earliest point that it’s safe to modify the DOM requires a bit of black magic, and the two libraries approach that in their own unique ways. Additionally, pageLoad() is overloaded with some extra functionality which may surprise you.

In this post, I’ll clarify the major differences between jQuery and ASP.NET AJAX’s initialization functions, what implications those difference have in practice, and show you a third alternative when working with ASP.NET AJAX.

Under the hood: $(document).ready()

As you would expect from John Resig, jQuery’s method for determining when the DOM is ready uses an assortment of optimizations.

For example, if a browser supports the DOMContentLoaded event (as many non-IE browsers do), then it will fire on that event. However, IE can’t safely fire until the document’s readyState reaches “complete”, which is typically later.

If none of those optimizations are available, window.onload will trigger the event.

Under the hood: pageLoad()

Instead of targeting browser-specific optimizations, the ASP.NET AJAX pageLoad() shortcut function is called as a result of a more uniform process.

That process is queued up the same way on all browsers, via a call to setTimeout with a timeout of 0 milliseconds. This trick leverages JavaScript’s single-threaded execution model to (theoretically) push the init event back until just after the DOM has finished loading.

Counter-intuitively, this isn’t the only point at which pageLoad() is called. It is also called after every partial postback. It basically functions as a combination of Application.Init and PageRequestManager.EndRequest.

Danger: UpdatePanels ahead

Since pageLoad() is called after every UpdatePanel refresh, the complications that arise can be initially difficult to grasp. For example, you’ll often see code like this:

<script type="text/javascript">
  function pageLoad() {
    // Initialization code here, meant to run once. 
  }
</script>
 
<asp:ScriptManager runat="server" />
 
<asp:UpdatePanel runat="server">
  <ContentTemplate>
    <asp:Button runat="server" ID="Button1" />
    <asp:Literal runat="server" ID="TextBox1" />
  </ContentTemplate>
</asp:UpdatePanel>

That initialization code will execute on the initial load, and things will seem okay at first. However, pageLoad() will then continue to be called each time Button1 is triggered, resulting in the initialization code running more often than intended.

This problem is similar to the classic ASP.NET mistake of forgetting to test for IsPostBack during the server-side Page_Load event. Depending on the nature of your initialization code, you may not even notice that there’s a problem, but it’s bound to catch up with you eventually.

In the case of initialization code that should run once, $(document).ready() is the ideal solution. It will do exactly what you need and nothing more.

Sometimes, pageLoad() is exactly what you want

While $(document).ready() is ideal for one-time initialization routines, it leaves you hanging if you have code that needs to be re-run after every partial postback. The LiveQuery functionality added in jQuery v1.3+ helps with this, but only works for a limited set of functionality.

For example, what if we wanted to add a jQueryUI datepicker to the TextBox in the previous example? Adding it in $(document).ready() would work great, until a partial postback occurred. Then, the UpdatePanel’s new TextBox element would no longer have the datepicker wired up to it. This is exactly where pageLoad() shines:

<script type="text/javascript">
  function pageLoad() {
    $('#TextBox1').unbind();
    $('#TextBox1').datepicker();
  }
</script>
 
<asp:ScriptManager runat="server" />
 
<asp:UpdatePanel runat="server">
  <ContentTemplate>
    <asp:Button runat="server" ID="Button1" />
    <asp:TextBox runat="server" ID="TextBox1" />
  </ContentTemplate>
</asp:UpdatePanel>

By attaching in pageLoad(), our TextBox will now have the datepicker attached to it on initial page load, and have it re-attached after every partial postback.

The call to unbind() is optional in this case, but a good precaution on more complex pages. Else, you run the risk of stacking multiple events on elements that were not refreshed as part of the partial postback.

An ASP.NET AJAX alternative to $(document).ready()

The previous sections should make it easier to decide between jQuery and ASP.NET AJAX’s events, but they assume you’re using both frameworks. What if you’re only using ASP.NET AJAX and want functionality similar to $(document).ready()?

Luckily, ASP.NET AJAX does provide a corresponding event. The Application.Init event fires only one time per page load, and is perfect for onetime initialization tasks. It’s not available through a shortcut function and requires slightly more caution, but serves its purpose:

<asp:ScriptManager runat="server" />
 
<script type="text/javascript">
  Sys.Application.add_init(function() {
    // Initialization code here, meant to run once.
  });
</script>

Note that the call to Application.add_init is placed after the ScriptManager. This is necessary because the ScriptManager injects its reference to MicrosoftAjax.js in that location. Attempting to reference the Sys object before that point will result in a “sys is undefined” JavaScript error.

If you think that limitation is a bit messy, you are not alone. I’m not a big fan of littering my presentation code with any more inline JavaScript than is necessary. To avoid this clutter, you may alternatively include your Application.Init code in an external file, included via a ScriptReference (see the previous link for an example).

Summary (tl;dr)

$(document).ready()

  • Ideal for onetime initialization.
  • Optimization black magic; may run slightly earlier than pageLoad().
  • Does not re-attach functionality to elements affected by partial postbacks.

pageLoad()

  • Unsuitable for onetime initialization if used with UpdatePanels.
  • Slightly less optimized in some browsers, but consistent.
  • Perfect for re-attaching functionality to elements within UpdatePanels.

Application.Init

  • Useful for onetime initialization if only ASP.NET AJAX is available.
  • More work required to wire the event up.
  • Exposes you to the “sys is undefined” error if you aren’t careful.

###

Originally posted at Encosia. If you’re reading this elsewhere, come on over and see the original.

$(document).ready() and pageLoad() are not the same!

Use jQuery to catch and display ASP.NET AJAX service errors

Another user fed up with your lack of error handling!

If you don’t properly handle the inevitable errors in your web applications, you can expect your users to eventually react about like this guy. Since they typically squelch any server-side errors, AJAX service calls are especially problematic. In fact, they rarely even throw a client-side error when they fail.

Even when a client-side error is thrown, most users won’t notice it and the ones who do notice won’t know what the error means or what to do next. In fact, I’ve found that even many developers don’t notice client-side scripting errors that occur while they’re debugging their own applications!

To help you remedy this problem in your own applications, I want to show you one way that I handle AJAX service call errors with jQuery. To do this, we will build an error-prone web service, make an AJAX request to it via jQuery, handle the resulting server-side errors gracefully, and use a jQuery plugin to attractively present those errors.

Building an erroneous method

To experiment with error handling, the first thing we’ll need is an error. We could use throw() to raise a synthetic error, but let’s build a page method that’s apt to throw a couple of real errors:

[WebMethod]
public static int DivideByZero(int Dividend)
{
  // To fool the compiler into not saving us from ourselves.
  int zero = 0;
 
  return (Dividend / zero);
}

If this method is called with a parameter that cannot be parsed as an integer, it will throw a type conversion error. If we do correctly call it with a string that can be converted to an integer, we’ll get a division by zero exception.

Using jQuery to call the page method

To interface with the page method, we’ll need an input field to supply the dividend and a button to trigger a call to the page method. Something like this:

<html>
<head>
  <title>Division by Zero Utility v1.0</title>
  <script type="text/javascript" src="jquery-1.3.2.min.js"></script>
  <script type="text/javascript" src="default.js"></script>
</head>
<body>
  <input type="text" id="Dividend" />
  <input type="button" id="Divide" value="Divide by 0" />
</body>
</html>

Using jQuery to call an ASP.NET AJAX page method is easy once you understand the required syntax and a few quirks. In default.js, we can use jQuery’s click() to wire our DivideByZero method up to the input button’s click event:

/// <reference path="~/jquery-1.3.2-vsdoc.js />
// When the page loads...
$(document).ready(function() {
  // ...attach an onclick handler to the Divide button.
  $("#Divide").click(function() {
    // Trigger a request to the page method.
    $.ajax({
      type: "POST",
      contentType: "application/json; charset=utf-8",
      dataType: "json",
      url: "Default.aspx/DivideByZero",
      // Supply the Dividend value from our input field.
      data: "{ 'Dividend': '" + $("#Dividend").val() + "' }",
      // Error!
      error: function(xhr, status, error) {
        // Display a generic error for now.
        alert("AJAX Error!");
      }
    });
  });
});

Notice the error callback function. This function will be raised in the event of any error or timeout when calling the service. For now, we’ll just display an alert() with a static error message.

If you were to run this example now, typing anything in the input field and hitting the “Divide by 0” button will result in the error handler being called. That’s better than nothing, but wouldn’t it be more useful to display specific information about the exception that occurred?

Inspecting the server’s response in Firebug

To improve the detail of our message, we need to dissect the error returned by the server and find where the specific detail lies. To accomplish this most effectively, I recommend using the Firebug addon to Firefox.

Using Firebug to set a breakpoint on the error handler, we’re able to inspect the request’s state at that point and quickly drill down to the information we’re after:

Inspecting the error's state, using a breakpoint in Firebug

While the status of “error” may seem unhelpful, it is a useful bit of information in some cases. In a more sophisticated error handling scenario, it would allow us to distinguish between a server-side error and a timeout.

However, the undefined error parameter certainly is not helpful.

To find the detail that we need, we’ll have to explore a bit further. Our request’s XMLHttpRequest instance should contain what we’re looking for. Clicking on the green XMLHttpRequest text will shift the Firebug window to inspect that specific object in detail:

Inspecting the XMLHttpRequest object in Firebug

Now we’re getting there: The XMLHttpRequest’s responseText property contains a JSON object with all the detail that the server returned.

As you can see in the Firebug screenshot, the Message variable contains a more familiar .NET error. In this case, indicating that the empty string I submitted was unsuitable for conversion to the Int32 parameter that DivideByZero expects.

Making effective use of the error data

As a string, this JSON object isn’t quite what we need. The last thing we should do is try to parse the error message ourselves. While technically possible, it would be messy and prone to breakage, or require using an extra library such as json2.js.

One of the nice things about JSON is that it is a native JavaScript construct. Thus, JavaScript’s eval() will evaluate a JSON string and return an actual JSON object.

To take advantage of that, we can modify the error handler like this:

error: function(xhr, status, error) {
  // Boil the ASP.NET AJAX error down to JSON.
  var err = eval("(" + xhr.responseText + ")");
 
  // Display the specific error raised by the server (e.g. not a
  //   valid value for Int32, or attempted to divide by zero).
  alert(err.Message);
}

Now, the properties of the error that we got a glimpse of in Firebug are available via the same dot-notation that you’d expect from any object. In particular, the errors returned by ASP.NET AJAX provide three variables in their JSON response: ExceptionType, Message, and StackTrace.

Note: I would normally recommend against using eval() to evaluate a JSON string. However, it is relatively safe in this case since these messages come directly from the .NET framework and do not contain any user-injected content.

Presenting the error message with jQuery

I’ve written about Mike Alsup’s BlockUI plugin before, showing you how to use it to display modal progress indication and confirmation windows. An often overlooked feature of the plugin is the ability to display basic “growl” style notifications.

See the demo at the bottom of this page for an example of that.

After adding a script reference to blockUI.js, displaying the error “growl” couldn’t be easier:

error: function(xhr, status, error) {
  var err = eval("(" + xhr.responseText + ")");
 
  // Display the error "growl", with a title of "Error",
  //  the error message as content, and a 20s display time.
  $.growlUI('Error', err.Message, 20000);
},
success: function() {
  // On the outside chance that our method manages to succeed, 
  //  clear any lingering error "growls".
  $.unblockUI();
}

Since it’s important that the user notice the error message, we can specify a much longer than default timeout for the “growl”. Twenty seconds in the example above.

The success handler is added to make sure any leftover error is cleared after a successful request completes. This avoids any confusion that would be caused by an error message remaining even after a successful request completes.

Because $.growlUI() is just a shortcut for a complex BlockUI usage, $.unblockUI() works on “growl” messages just as if they were $.blockUI() modals.

Note: As with the rest of BlockUI, these “growl” messages can be customized via CSS. For this simple demo, I’m happy with the default styling, but you can easily change it to match your application.

Conclusion

You should never assume your service calls are 100% reliable. This seems obvious, but I’ve encountered mountains of production code without error handling.

As you’ve hopefully seen in this post, it is trivially easy to add great looking error handling to your jQuery service calls. After all is said and done, you’re only looking at about 3-5 extra lines of code. This substantial improvement in usability is well worth the minimal effort.

We focused on an example of using a page method here, but keep in mind that this technique can be implemented to work with both page methods and web service calls.

Source

Download source: jquery-error-handling.zip

###

Originally posted at Encosia. If you’re reading this elsewhere, come on over and see the original.

Use jQuery to catch and display ASP.NET AJAX service errors

Projective transformation and perspective in Javascript

projective_js_20090224.jpg

Javascript only supports affine transformations in the Canvas element. In plain English, this means you have control over simple transformations like rotation, scale, and skew. Rendering something with perspective, however, involves a projective transformation and there are no 3D transformation operations within the official Canvas spec to support this sort of thing.

Steven Wittens hacked some code to bypass this limitation and approximate projection transformations. It works by chopping up the source image into several pieces and applying affine transformations to each of the pieces to approximate their projected size and position. If the slices are small enough, it’s barely noticeable.

Perspective views are described by so-called projective transforms, which Canvas2D does not support. However, it does support arbitrary clipping masks as well as affine transforms of both entire and partial images. These can be used to do a fake projective transform: you cut up your textured surface into a bunch of smaller patches (which are almost-affine) and render each with a normal affine transform. Of course you need to place the patches just right, so as to cover any possible gaps. As long as the divisions are small enough, this looks convincingly 3D.

This technique is used in everything from Flash 3D engines to texturing in some PC and console games, but I’m impressed to see it functioning so well in Javascript.

Projective Texturing with Canvas

A breaking change between versions of ASP.NET AJAX

When working directly with JSON serialized ASMX services, be it via jQuery, pure XmlHttpRequest calls, or anything else other than the ScriptManager, one question inevitably arises. That question is of the inexplicable .d attribute that appeared in ASP.NET 3.5.

What is it? Why is it there?

In this post, I’ll use both a 2.0 and a 3.5 example ASMX web service to illustrate exactly what’s going on. I’ll also show you why it’s a good change.

An example

Following a concrete example always helps to better clarify these things. For that purpose, let’s assume that we want to call a web service and retrieve an instance of the following Person class:

public class Person
{
  public string FirstName;
  public string LastName;
}

The ASMX web service to return an instance of that class could be simple as this:

[ScriptService]
public class PersonService : WebService
{
  [WebMethod]
  public Person GetPerson()
  {
    Person p = new Person();
 
    p.FirstName = "Dave";
    p.LastName = "Ward";
 
    return p;
  }
}

Because our WebService class is decorated with the [ScriptService] attribute, the ASP.NET AJAX Extensions (System.Web.Extensions) will automatically serialize the return value as JSON if properly requested.

Note: A common anti-pattern that I’ve seen in practice is using a return type of string and returning a manually JSON serialized object. Don’t. It’s unnecessary and results in doubled effort on both the server and in the browser.

Let the framework handle this task unless you have a good reason not to use the built-in functionality. It works just fine in most scenarios.

Calling the service and inspecting its result

Using jQuery to consume an ASMX web service is simple, but does require jumping through a few hoops. We can use this jQuery to consume the Person service we just created:

$.ajax({
  type: "POST",
  contentType: "application/json; charset=utf-8",
  url: "PersonService.asmx/GetPerson",
  data: "{}",
  dataType: "json",
  success: function(msg) {
    // Do interesting things here.
  }
});

Making that call against an ASP.NET 2.0 site with the ASP.NET AJAX Extensions 1.0 installed, this JSON object would be the return value:

2.0 JSON Response in Firebug

I find that it often helps to visualize the JSON in a more human readable format. This is the same JSON object as seen in the Firebug screenshot above:

{"__type"    : "Person",
 "FirstName" : "Dave",
 "LastName"  : "Ward"}

Within the success callback shown above, you may access properties of the Person exactly as you would expect. For example, msg.FirstName will evaluate to “Dave”.

Waiter, there’s a .d in my msg soup!

Eventually, you’ll finally convince management to let you upgrade the site to ASP.NET 3.5. After all, you can use an object initializer to cut the size of the web service in half!

However, your msg.FirstName statement now results in the dreaded undefined.

What happened? Let’s inspect the ASP.NET 3.5 response in Firebug:

3.5 JSON Response in Firebug

The entire Person object is wrapped within a new “d” object now. Alternatively we might visualize it this way:

{"d":{"__type"    : "Person",
      "FirstName" : "Dave",
      "LastName"  : "Ward"}}

As you’ve probably figured out by now, the solution is to reference the property as msg.d.FirstName now. In our example, this will again resolve correctly as “Dave”.

This is the case with all ASMX services JSON serialized through the ASP.NET AJAX Extensions in ASP.NET 3.5. Even if you’re only returning a scalar return value, such as a string, int, or boolean, the result will always be enclosed within the “d”.

Why did it change?

While I wish this unexpected change had been more clearly announced, it’s a good one. Here’s how Dave Reed explained it to me:

{"d": 1 }

 

Is not a valid JavaScript statement, where as this:

 

[1]

 

Is.

 

So the wrapping of the "d" parameter prevents direct execution of the string as script. No Object or Array constructor worries.

[] is JavaScript’s array literal notation, allowing you to instantiate an array without explicitly calling a constructor. To expand on Dave’s explanation, simply consider this code:

["Dave", alert("Do Evil"), "Ward"]

That literal array declaration will execute the alert in most browsers. Danger!

Update: For an even better description of why the .d is important, from Dave Reed himself, be sure to see his comment below.

Conclusion

I hope this post has helped clarify any confusion caused by the “d” in ASP.NET 3.5’s JSON serialized ASMX services, and made you aware of why it’s worth the hassle. As sophisticated as XSS exploits have become in recent years, unexpected script execution has the potential for devastating consequences. That extra “d” is well worth the short-term hassle.

Microsoft often catches flak over security related issues, but rarely gets credit when they do things right. I, for one, think the ASP.NET team deserves credit for remaining vigilant and often preempting these exploits for us.

Thanks, guys.

###

Originally posted at Encosia. If you’re reading this elsewhere, come on over and see the original.

A breaking change between versions of ASP.NET AJAX

WP Like Button Plugin by Free WordPress Templates