15

After trying to format my JSON data by hand in javascript and failing miserably, I realized there's probably a better way. Here's what the code for the web service method and relevant classes looks like in C#:

[WebMethod]
public Response ValidateAddress(Request request)
{
    return new test_AddressValidation().GenerateResponse(
        test_AddressValidation.ResponseType.Ambiguous);
}

...

public class Request
{
    public Address Address;
}

public class Address
{
    public string Address1;
    public string Address2;
    public string City;
    public string State;
    public string Zip;
    public AddressClassification AddressClassification;
}

public class AddressClassification
{
    public int Code;
    public string Description;
}

The web service works great with using SOAP/XML, but I can't seem to get a valid response using javascript and jQuery because the message I get back from the server has a problem with my hand-coded JSON.

I can't use the jQuery getJSON function because the request requires HTTP POST, so I'm using the lower-level ajax function instead:

$.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: "http://bmccorm-xp/HBUpsAddressValidation/AddressValidation.asmx/ValidateAddress",
    data: "{\"Address\":{\"Address1\":\"123 Main Street\",\"Address2\":null,\"City\":\"New York\",\"State\":\"NY\",\"Zip\":\"10000\",\"AddressClassification\":null}}",
    dataType: "json",
    success: function(response){
        alert(response);
    }
})

The ajax function is submitting everything specified in data:, which is where my problem is. How do I build a properly formatted JSON object in javascript so I can plug it in to my ajax call like so:

data: theRequest

I'll eventually be pulling data out of text inputs in forms, but for now hard-coded test data is fine.

How do I build a properly formatted JSON object to send to the web service?


UPDATE: It turns out that the problem with my request wasn't the formatting of the JSON, as T.J. pointed out, but rather that my JSON text didn't conform to requirements of the web service. Here's a valid JSON request based on the code in the WebMethod:

'{"request":{"Address":{"Address1":"123 Main Street","Address2":"suite 20","City":"New York","State":"NY","Zip":"10000","AddressClassification":null}}}'

This brought up another question: When is case sensitivity important in JSON requests to ASP.NET web services (ASMX)?

5
  • Completely OT, but looking at your data: "{\"Address\":{\"Address1\" ... }";, remember that in Javascript you can use single quotes to delimit your strings, so that gets a lot more readable: data: '{"Address":{"Address1" ... }', (of course, be sure to escape any ' characters that appear in the data, but at least there are a lot fewer of them than " characterss. Commented Apr 29, 2010 at 13:18
  • @T.J. I appreciate the tip. My javascript neophyte colors are showing :-) Commented Apr 29, 2010 at 13:20
  • 1
    :-) Re your question to jhurshman on an answer that has since been deleted, about JSON vs. Javascript object literal notation: JSON is a subset of Javascript object literal notation, see json.org for details. But they're very similar (of course). In your quoted code, the string you were outputting was perfectly valid JSON. (This site is sometimes useful: jsonlint.com) Commented Apr 29, 2010 at 13:26
  • 1
    @T.J. Thanks for the link to jsonlint. I was wishing for a tool like that all afternoon the other day. Commented Apr 29, 2010 at 13:32
  • I don't think you get notified of edits, so: I had a thought about why it might be rejecting your (valid) JSON and have updated my answer -- is it perhaps expecting an object that is an Address, rather than an object with the property "Address" which contains the address? (See the answer for details.) Commented Apr 29, 2010 at 13:50

7 Answers 7

13

The answer is very easy and based on my previous posts Can I return JSON from an .asmx Web Service if the ContentType is not JSON? and JQuery ajax call to httpget webmethod (c#) not working.

The data should be JSON-encoded. You should separate encode every input parameter. Because you have only one parameter you should do like following:

first construct you data as native JavaScript data like:

var myData = {Address: {Address1:"address data 1",
                        Address2:"address data 2",
                        City: "Bonn",
                        State: "NRW",
                        Zip: "53353",
                        {Code: 123,
                         Description: "bla bla"}}};

then give as a parameter of ajax request {request:$.toJSON(myData)}

$.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: "http://bmccorm-xp/HBUpsAddressValidation/AddressValidation.asmx/ValidateAddress",
    data: {request:$.toJSON(myData)},
    dataType: "json",
    success: function(response){
        alert(response);
    }
})

instead of $.toJSON which come from the JSON plugin you can use another version (JSON.stringify) from http://www.json.org/

If your WebMethod had parameters like

public Response ValidateAddress(Request request1, Request myRequest2)

the value of data parameter of the ajax call should be like

data: {request1:$.toJSON(myData1), myRequest2:$.toJSON(myData2)}

or

data: {request1:JSON.stringify(myData1), myRequest2:JSON.stringify(myData2)}

if you prefer another version of JSON encoder.

Sign up to request clarification or add additional context in comments.

4 Comments

By the way it is not required to use POST in ajax. Everything work also with GET. For more information see my links from the beginning of the answer. The problem with JSON Hijacking exist see (haacked.com/archive/2009/06/25/json-hijacking.aspx), but there are different ways to reduce the risk and one should continue GET usage.
+1 for correctly identifying that the data needed to be wrapped in request in order to work.
you nailed it. This exactly answers why my code wasn't working and how the JSON data needed to be formatted. Much thanks!
Ah, the request bit was the bit that was missing. Good to know.
5

Your problem breaks down into two parts:

Creating the JSON string

Your JSON in your quoted code is perfectly valid. But being hand-crafted is a pain. As others have called out, the easiest way to do this is to create a Javascript object and then JSON.stringify it. Example:

var data = {
    "Address": {
        "Address1": "123 Main Street",
        "Address2": null,
        "City": "New York",
        "State": "NY",
        "Zip": "10000",
        "AddressClassification": null
    }
};
data = JSON.stringify(data);

The first step above creates an object using Javascript object literal notation, which is a superset of JSON (as used above, it actually is the same as JSON, but ignore that). The second bit takes that object and converts it to a string.

Of course, the values above are literal strings, which is unlikely. Here's what it would look like if you had each of those values in a variable:

var data = {
    "Address": {
        "Address1": address1,
        "Address2": address2,
        "City": city,
        "State": state,
        "Zip": zip,
        "AddressClassification": null
    }
};
data = JSON.stringify(data);

Either way, now you have the string.

Sending the JSON string to the web service

You need to find out is whether the web service is expecting the JSON-formatted data to be the POST body, or if it's expecting the JSON data to be the value of a parameter in the more common name=value URL-encoded POST data. I would tend to expect the former, because the web service seems specifically designed to work with JSON-formatted data.

If it's supposed to be the POST body, well, I've never done that with jQuery, and what you have quoted looks correct to me reading the docs. If it's not working, I'd double-check that your object structure is really what they're expecting to see. For instance, if it's just validating a single address, I wonder if it's expecting to receive just an Address object, rather than an object containing an Address object, e.g.:

{
    "Address1": "123 Main Street",
    "Address2": null,
    "City": "New York",
    "State": "NY",
    "Zip": "10000",
    "AddressClassification": null
}

If it's supposed to be the value of a parameter in boring old URL-encoded multipart form data, then:

$.ajax({
    type: "POST",
    url: "http://bmccorm-xp/HBUpsAddressValidation/AddressValidation.asmx/ValidateAddress",
    data: "paramname=" + encodeURIComponent(data),
    dataType: "json",
    success: function(response){
        alert(response);
    }
})

I've removed the contentType so jQuery will fall back to its default ("application/x-www-form-urlencoded") and ensured the string we created above is properly encoded in that content type. You'll need to find out the paramname to use (perhaps "Address" and see my earlier comment about sending just the address, rather than an object containing an address child object?).

2 Comments

As it turns out, the web service is expecting a request object which contains an address object. That ended up being the reason my request failed. See my update to the question for further details and thanks for your detailed explanations.
@Ben: Ah, good! Yeah, saw your new question, but don't have a clue about it (I've never used ASP.Net web sevice stuff). Javascript names are case-sensitive, but that doesn't mean that .Net has to treat JSON data that way.
1

JSON.stringify will take a javascript object and turn it into a string. I bet though that if you create a Javascript object like

var jsonData = {
    address: 'address',
    address1: 'address1',
    address2: 'address2'
};

and then pass in jsonData as 'data' in the ajax call, then it will convert the object to json text for you.

Comments

1

I would create a javascript object and then call JSON.stringify to turn it into valid JSON. You can download it from here.

You could do something like this:

var address= {};

address["Address1"] = "your val";
address["Address2"] = "your val";
address["City"] = "your val";
address["State"] = "your val";
address["Zip"] = "your val";

$.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: "http://bmccorm-xp/HBUpsAddressValidation/AddressValidation.asmx/ValidateAddress",
    data: JSON.stringify(address),
    dataType: "json",
    success: function(response){
        alert(response);
    }
});

5 Comments

Agreed on creating an object and then JSON.stringify'ing it, but why in heaven's name would he create the object so indirectly? This will lose something because I can't do linebreaks, but: var address = {Address: {Address1: "123 Main Street", .... }; is a much cleaner way to create that object. (Also, the object you were creating was in a slightly different form than the one he creates with his JSON.)
I agree, it is a bit indirect...I'm assuming that he's pulling his data from some form field, so "your val"; would actually be $("#formElement").val();
Yeah, but even then, I'd write it {Address: {Address1: $("#address1Element").val(), Address2: $("#address2Element").val(), ... }} rather than constantly re-referencing the var. But either way. :-)
yep, your way is definitely shorter, but either way works. You could also go another way and give your form fields the same name as your object properties and do this: $(':text').each(function() { address[this.id] = this.value; });
Indeed. :-) And in fact, I do that with some forms, can be quite handy.
1

You need to pass it like this:

$.ajax({
  type: "POST",
  url: "WebService.asmx/WebMethodName",
  data: "{'fname':'dave', 'lname':'ward'}",
  contentType: "application/json; charset=utf-8",
  dataType: "json"
});

Have a look at this article for more details: 3 mistakes to avoid when using jQuery with ASP.NET AJAX

2 Comments

@Giorgi that's exactly where my sample code came from at first. I have the general structure of the ajax function down, I think; it's the formatting of the data that I'm having trouble with.
@Giorgi: That's invalid JSON. Keys must be in double, not single, quotes.
1

All apologies if this answer comes too late, or is a duplication.

From what I understand, it appears as though you're trying to send just the string of a JSON object. Try building an object and then working with its properties and sending it in as it is.

Example:

address = new Object();
address.Address = new Object();
address.Address.Address1 = "123 Main Street";
address.Address.Address2 = "";
address.Address.City = "New York";
address.Address.State = "NY";
address.Address.Zip = "10000";
address.Address.AddressClassification = null;
$.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: "http://bmccorm-xp/HBUpsAddressValidation/AddressValidation.asmx/ValidateAddress",
    data: address,
    dataType: "json",
    success: function(response){
        alert(response);
    }
});

Comments

0

Get yourself a jquery plugin that can convert any javascript object to json. For example:

http://plugins.jquery.com/project/json

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.