I'm not sure where I'm going wrong of what I'm missing.
I'm building an ASP.NET 2.0 (on the .Net 3.5 framework) Web application and I am including a webservice. Note that this is not an MVC project. I wish to expose a method which will return a JSON string; formatted to feed the jqGrid jQuery plugin.
This is the preliminary test method I've implemented in my service: thanks to (Phil Haack's Guide for MVC)
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string getData()
{
JavaScriptSerializer ser = new JavaScriptSerializer();
var jsonData = new
{
total = 1, // we'll implement later
page = 1,
records = 3, // implement later
rows = new[]{
new {id = 1, cell = new[] {"1", "-7", "Is this a good question?", "yay"}},
new {id = 2, cell = new[] {"2", "15", "Is this a blatant ripoff?", "yay"}},
new {id = 3, cell = new[] {"3", "23", "Why is the sky blue?", "yay"}}
}
};
return ser.Serialize(jsonData); //products.ToString();
}
When invoked this is returning (formatted for clarity):
<?xml version="1.0" encoding="utf-8" ?>
<string mlns="http://tempuri.org/">
{
"total":1,
"page":1,
"records":3,
"rows":
[
{"id":1,"cell":["1","-7","Is this a good question?","yay"]},
{"id":2,"cell":["2","15","Is this a blatant ripoff?","yay"]},
{"id":3,"cell":["3","23","Why is the sky blue?","yay"]}
]
}
</string>
How would I achieve the above response without the xml wrappings?
[WebMethod]
public static void GetDocuments()
{
HttpContext.Current.Response.ContentType = "application/json";
HttpContext.Current.Response.Write(JsonConvert.SerializeObject( ^_^ ));
HttpContext.Current.Response.End();
}
I've had better luck with doing the following:
[WebMethod]
public static void GetDocuments()
{
HttpContext.Current.Response.ContentType = "application/json";
HttpContext.Current.Response.Write(JsonConvert.SerializeObject(repository.GetDocuments()));
HttpContext.Current.Response.End();
}
It's important to set the content type properly, and to write the JSON directly to the respond, then to end the response so that no further data is sent to corrupt your response. An advantage of this architecture is you can use whatever serializer you want, you're not limited to the built in JSON serializer. In this case, I used Json.NET.
I realize that this is abusing the architecture (and I personally dislike having a void return type for something that's supposed to return data) but this is the only truly reliable method I've found.
On the other hand, you should be switching to WCF or Web API, for reasons John Saunders describes here. Web API in particular is very easy to use, and allows for content type negotiation between the client and server.
Three things you may not be doing:
There may be a way to call the method with a GET, I've only ever used POST. I was able to get your example working with this:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script>
// In your javascript block
$(document).ready(function()
{
$.ajax({
url: "/Default.aspx/Tester",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "{}",
success: done
});
});
function done(data)
{
// Include http://www.json.org/json2.js if your browser doesn't support JSON natively
var data = JSON.parse(data.d);
alert(data.total);
}
</script>
The code behind (you don't need to create a webservice, you can put this in your default.aspx):
[WebMethod]
public static string Tester()
{
JavaScriptSerializer ser = new JavaScriptSerializer();
var jsonData = new
{
total = 1, // we'll implement later
page = 1,
records = 3, // implement later
rows = new[]{
new {id = 1, cell = new[] {"1", "-7", "Is this a good question?", "yay"}},
new {id = 2, cell = new[] {"2", "15", "Is this a blatant ripoff?", "yay"}},
new {id = 3, cell = new[] {"3", "23", "Why is the sky blue?", "yay"}}
}
};
return ser.Serialize(jsonData); //products.ToString();
}
The result:
{"d":"{\"total\":1,\"page\":1,\"records\":3,\"rows\":[{\"id\":1,\"cell\":[\"1\",\"-7\",\"Is this a good question?\",\"yay\"]},{\"id\":2,\"cell\":[\"2\",\"15\",\"Is this a blatant ripoff?\",\"yay\"]},{\"id\":3,\"cell\":[\"3\",\"23\",\"Why is the sky blue?\",\"yay\"]}]}"}
A more detailed explanation is here
In your code, don't "return" the json. Use instead:
Context.Response.Write(ser.Serialize(jsonData));
Then you'll be good.
The regular return command helps you by putting in a more proper service format. Some would say it'd be better form to use this, and unwrap your json on the client from this format. I say, just spit down the stuff exactly how you want to use it!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With