ajax解析properties,AJAX result.d实例解释

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:

a4c26d1e5885305701be709a3d33442f.png

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:

a4c26d1e5885305701be709a3d33442f.png

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.