65

I created an ASMX file with a code behind file. It's working fine, but it is outputting XML.

However, I need it to output JSON. The ResponseFormat configuration doesn't seem to work. My code-behind is:

[System.Web.Script.Services.ScriptService]
public class _default : System.Web.Services.WebService {
    [WebMethod]
    [ScriptMethod(UseHttpGet = true,ResponseFormat = ResponseFormat.Json)]
    public string[] UserDetails()
    {
        return new string[] { "abc", "def" };
    }
}
doekman
  • 18,750
  • 20
  • 65
  • 86
  • Possible duplicate of [Asmx web service how to return JSON without an XML wrapper?](https://stackoverflow.com/questions/14950578/asmx-web-service-how-to-return-json-without-an-xml-wrapper) – Stephen Kennedy Feb 21 '18 at 12:42

6 Answers6

60

To receive a pure JSON string, without it being wrapped into an XML, you have to write the JSON string directly to the HttpResponse and change the WebMethod return type to void.

    [System.Web.Script.Services.ScriptService]
    public class WebServiceClass : System.Web.Services.WebService {
        [WebMethod]
        public void WebMethodName()
        {
            HttpContext.Current.Response.Write("{property: value}");
        }
    }
sshow
  • 8,820
  • 4
  • 51
  • 82
iCorrect
  • 617
  • 5
  • 2
  • Also works when you want to return XML without an extra XML wrapper. – kad81 Apr 03 '14 at 02:55
  • 1
    No, you really don't have to do that, as the other answers prove. I have plenty of legacy services returning either JSON or XML depending on what the web client asks for and have never had to resort to writing directly to the Response stream. – Stephen Kennedy Dec 22 '17 at 14:24
39

From WebService returns XML even when ResponseFormat set to JSON:

Make sure that the request is a POST request, not a GET. Scott Guthrie has a post explaining why.

Though it's written specifically for jQuery, this may also be useful to you:
Using jQuery to Consume ASP.NET JSON Web Services

Community
  • 1
  • 1
Pavel Chuchuva
  • 22,633
  • 10
  • 99
  • 115
  • 8
    alternatively you also can add the following annotation [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)] public string TestData() to enable GET in your webservices – Mario Fraiß Mar 06 '12 at 21:21
  • 1
    Wow. Who would've guessed that you couldn't get a `JSON` response with a `GET` request. Unbelievable. Thanks for this - I was tearing my hair out! – crush Jan 14 '14 at 14:37
  • 4
    I don't agree that a POST request is appropriate here. The endpoint is not expecting data and the OP is not sending any data to the server (unlike Scott G's post) and certainly not intending to change data on the server. In fact the OP has the correct ScriptMethod attribute to allow a GET request - UseHttpGet=true. They are simply invoking an endpoint to 'get' some data. A GET request is fine - all that's missing is setting the Content-Type in the request, see my answer below. – bitsprint Jan 20 '14 at 15:35
  • Slightly off-topic but relevant. The Encosia URL above triggers a scary security warning on Chrome saying the site contains Malware. – Totoro53 Aug 04 '17 at 07:56
  • This is at best only part of the story. – Stephen Kennedy Feb 21 '18 at 12:42
18

This is probably old news by now, but the magic seems to be:

  • [ScriptService] attribute on web service class
  • [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)] on method
  • Content-type: application/json in request

With those pieces in place, a GET request is successful.

For a HTTP POST

  • [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)] on method

and on the client side (assuming your webmethod is called MethodName, and it takes a single parameter called searchString):

        $.ajax({
            url: "MyWebService.asmx/MethodName",
            type: "POST",
            contentType: "application/json",
            data: JSON.stringify({ searchString: q }),
            success: function (response) {                  
            },
            error: function (jqXHR, textStatus, errorThrown) {
                alert(textStatus + ": " + jqXHR.responseText);
            }
        });
Matthew Lock
  • 13,144
  • 12
  • 92
  • 130
marc
  • 3,248
  • 4
  • 28
  • 33
  • The interesting thing is that the application/json is required, and when not there, it will return the XML from my experience with Fiddler. Kinda a hacky way of returning both data types? – SimpsOff Oct 18 '12 at 15:44
  • 3
    Why in the world is it required to set `Content-type` to `application/json`? Shouldn't `[ScriptMethod(ResponseFormat=ResponseFormat.Json)]` do that automatically? Unbelievable. Thanks for the research. – crush Jan 14 '14 at 14:39
  • `[ScriptMethod...` seems to have trouble compiling in my case. It's having trouble finding the definition for `UseHttpGet`, and if I try to import `ScriptMethodAttribute` or say `ScriptMethodAttribute.UseHttpGet`, then it says that a constant expression is required. – Panzercrisis Jul 18 '16 at 14:17
  • I think I see now. I was using ` – Panzercrisis Jul 18 '16 at 14:29
  • 1
    `[ScriptService]` on class level, those on function level: `[WebMethod(EnableSession = true)]`, `[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]` and havng `HttpContext.Current.Response.ContentType = "application/json";` as first line in the function body still results in a xml output. – Anders Lindén Feb 16 '17 at 09:57
9

A quick gotcha that I learned the hard way (basically spending 4 hours on Google), you can use PageMethods in your ASPX file to return JSON (with the [ScriptMethod()] marker) for a static method, however if you decide to move your static methods to an asmx file, it cannot be a static method.

Also, you need to tell the web service Content-Type: application/json in order to get JSON back from the call (I'm using jQuery and the 3 Mistakes To Avoid When Using jQuery article was very enlightening - its from the same website mentioned in another answer here).

Astra
  • 10,735
  • 3
  • 37
  • 41
4

Alternative: Use a generic HTTP handler (.ashx) and use your favorite json library to manually serialize and deserialize your JSON.

I've found that complete control over the handling of a request and generating a response beats anything else .NET offers for simple, RESTful web services.

Kevin
  • 1,829
  • 1
  • 21
  • 22
4

Are you calling the web service from client script or on the server side?

You may find sending a content type header to the server will help, e.g.

'application/json; charset=utf-8'

On the client side, I use prototype client side library and there is a contentType parameter when making an Ajax call where you can specify this. I think jQuery has a getJSON method.

bitsprint
  • 897
  • 1
  • 11
  • 19
  • This is the correct answer in my mind. While it is good advice to use a post request, there's nothing wrong with the code as it is written in the OP. The likely culprit is that the content type header is wrong. JQuery for example does send 'application/json' on it's own, but includes some additional 'text/xml' values that causes asp.net to still return xml. – b_levitt Dec 28 '13 at 21:41