Note: This post is part of a long-running series of posts covering the union of jQuery and ASP.NET: jQuery for the ASP.NET Developer.

Topics in this series range all the way from using jQuery to enhance UpdatePanels to using jQuery up to completely manage rendering and interaction in the browser with ASP.NET only acting as a backend API. If the post you're viewing now is something that interests you, be sure to check out the rest of the posts in this series.

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.