Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing ASP.net webservice to return JSON

Tags:

I have an ASP.net web service that I'm using for a web application which returns a either XML or JSON data to me, depending on the function I call. This has been working well thus far, but I've run into a problem. I want to create an "export" link on my page that will download a JSON file. The link is formatted very simply:

<a href="mywebserviceaddress/ExportFunc?itemId=2">Export This Item</a>

As you might imagine, this should export item 2. So far so good, yes?

Problem is that since I'm not specifically requesting that the accepted content type is JSON, ASP.net absolutely refuses to send back anything but XML, which just isn't appropriate for this situation. The code is essentially as follows:

    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public Item ExportItem(int itemId)
    {
        Context.Response.AddHeader("content-disposition", "attachment; filename=export.json"); //Makes it a download

        return GetExportItem(itemId);
    }

Despite my specifying the ResponseFormat as JSON, I always get back XML unless I request this method via AJAX (using Google Web Toolkit, BTW):

    RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, "mywebserviceaddress/ExportFunc");
    builder.setHeader("Content-type","application/json; charset=utf-8");
    builder.setHeader("Accepts","application/json");
    builder.sendRequest("{\"itemId\":2}", new RequestCallback(){...});

That's great, but AJAX won't give me a download dialog. Is there any way to force ASP.net to give me back JSON, regardless of how the data is requested? It would seem to me that not having a manual override for this behavior is a gross design oversight.


QUICK ANSWER:

First off, let me say that I think that womp's answer is probably the better way to go long term (Convert to WCF), but deostroll led me to the answer that I'll be using for the immediate future. Also, it should be noted that this seems to work primarily because I wanted just a download, may not work as well in all situations. In any case, here's the code that I ended up using to get the result I wanted:

    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public void ExportItem(int itemId)
    {
        Item item = GetExportItem(itemId);            

        JavaScriptSerializer js = new JavaScriptSerializer();
        string str = js.Serialize(item);

        Context.Response.Clear();
        Context.Response.ContentType = "application/json";
        Context.Response.AddHeader("content-disposition", "attachment; filename=export.json");
        Context.Response.AddHeader("content-length", str.Length.ToString());
        Context.Response.Flush();
        Context.Response.Write(str);
    }

Please note the return type of void (which means that your WDSL will be next to useless for this function). Returning anything will screw up the response that is being hand-built.

like image 733
Toji Avatar asked Sep 09 '09 19:09

Toji


People also ask

Can soap return JSON?

SOAP relies exclusively on XML to provide messaging services, so if you really want/need to return JSON then you would need to wrap it in CDATA in the SOAP XML body. Unlike SOAP, however, REST does not have to use XML to provide the response, therefore you can output the data in other formats such as JSON.


2 Answers

Asp.net web services are SOAP-based web services. They'll always return XML. The Ajax libraries came along and the ScriptMethod stuff was introduced, but it doesn't change the underlying concept of it.

There's a couple things you can do.

WebMethods are borderline obsolete with the introduction of WCF. You might consider migrating your web services to WCF, in which you'll have much greater control over the output format.

If you don't want to do that, you can manually serialize the result of your webservice calls into JSON, and the service will wrap that in a SOAP header. You would then need to strip out the SOAP stuff.

like image 58
womp Avatar answered Sep 29 '22 06:09

womp


Here are two forums threads for your reference:

http://forums.asp.net/t/1118828.aspx

http://forums.asp.net/p/1054378/2338982.aspx#2338982

I have no clear idea. They say on concentrating on setting the content type to application/json. I haven't worked with wcf before, but I think you can make use of the Response object.

Set the content type on the response object. Do a response.write passing your json data as string and then do a response.end.

like image 31
deostroll Avatar answered Sep 29 '22 06:09

deostroll