Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET WebService is Wrapping my JSON response with XML tags

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?

like image 488
Mike Avatar asked Jan 13 '10 16:01

Mike


4 Answers

  1. turn the return type to void
  2. put your object onto ^_^
[WebMethod]
public static void GetDocuments()
{
    HttpContext.Current.Response.ContentType = "application/json";
    HttpContext.Current.Response.Write(JsonConvert.SerializeObject( ^_^ ));
    HttpContext.Current.Response.End();
}
like image 62
Spokemind Avatar answered Nov 11 '22 19:11

Spokemind


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.

like image 25
mason Avatar answered Oct 12 '22 12:10

mason


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"></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

like image 10
Chris S Avatar answered Nov 11 '22 18:11

Chris S


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!

like image 10
Patrick Karcher Avatar answered Nov 11 '22 20:11

Patrick Karcher