views:

236

answers:

3

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/"&gt;
{
  "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?

+1  A: 

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!

Patrick Karcher
This seems to work if you navigate to the .aspx page then follow the linkage through to invoke. Unfortunately if I try to navigate to "GridDataRequest.asmx/getData" I get a yellow screen of death "Request format is unrecognized for URL unexpectedly ending in '/getData'."
Mike
+1 for this handy gem of code. I've however chosen another solution to better-fit with our model.
Mike
Yep, better to use json.parse, as long as you're using jquery anyway. More proper.
Patrick Karcher
+1  A: 

When you mark the service as a ScriptService, it automatically handles the JSON serialization. You shouldn't manually serialize the response. See this stack overflow entry for more detail.

Anthony
A: 

Three things you may not be doing:

  • Marking the method static
  • Performing a POST
  • Hand an empty "{ }" for the data in jQuery.

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"&gt;&lt;/script&gt;
<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

Chris S
How did you get your result. When I implement as you have I seem to only get "[object Object]" back. This could be naivety to JSON, but I can't seem to get it to work.
Mike
I used firebug in Firefox to view the response from the Net panel - click the response tab for that request.
Chris S
Do you know why the data is being wrapped in the variable "d"?
Mike
I've updated my answer. jQuery adds the 'd' to it.
Chris S
Thanks for a very well earned accepted answer! :)
Mike
curious why this has been downvoted
Chris S
The "d" isn't added by jQuery but .NET 3.5 as a security measure.
Chris S