views:

98

answers:

2

I'm trying to call a web service (.asmx) from a c# application, in json format.

When I specify request method as GET, and don't specify contentType.

(req is HttpWebRequest)

req.Method = "GET";

Everything works well, but I get XML response.
When I specify content Type:

req.ContentType = "application/json; charset=utf-8";  

I get

500 internal server error.

When I change request method:

req.Method = "POST";  

I can call parameterless methods only, which returns correctly json, but if I try calling a method with parameters, I get 500 error again.

The web service code:

    [WebMethod(EnableSession =true)]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public string SimplestWebService()
    {         
        return "hello";
    }  

And With parameters:

    [WebMethod(EnableSession = true)]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public string Echo(string aString)
    {       
        return aString;
    }

Any ideas will be much appreciated.

Added: Maybe I'm not writing the POST request right (now I'm sending it in the header, just like a GET request). Can someone please guide me on that?

Mode added: The web site is indeed marked as script:

[ScriptService]
public class MyAPI : System.Web.Services.WebService  

And here is how I build my POST request (I really tend to believe that's the problem):

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(methodUrl.ToString());
req.Method = "POST";
req.Headers.Add("aString","oren");
req.ContentLength = 0;    
...
req.ContentType = "application/json; charset=utf-8";
req.Accept = "application/json; charset=utf-8";
using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
{
  StreamReader sr = new StreamReader(res.GetResponseStream());
  result.Append(sr.ReadToEnd());
}  
...

Also tried:

req.Method = "POST";          
string postData = "aString=kjkjk";
req.ContentType = @"application/json; charset=utf-8";
req.Accept = @"application/json; charset=utf-8";   
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byte1 = encoding.GetBytes(postData);
req.ContentLength = byte1.Length;
Stream newStream = req.GetRequestStream();
newStream.Write(byte1, 0, byte1.Length);
newStream.Close();           

Two last notes:
1. This web service works in XML using the browser.
2. Asking for json, the code never reaches a break point at the web service. So this is possibly a IIS (I'm using IIS 6.1) issue. I've tried the MIME type recommendation here.

Thanks a lot.

A: 

ContentType seems to me to be the content-type of the request, not the response. What happens if you send an Accept header instead (informing the server of the content-types you're willing to accept).

Wrikken
@Wrikken: Exactly the same results as before, both with GET and POST.
Oren A
Checked it in Fiddler, and I'm getting a json response: {"Message":"There was an error processing the request.","StackTrace":"","ExceptionType":""} (and 500 internal server error at the header)
Oren A
Moreover, if I try omitting the contentType, I get an XML response.
Oren A
Are you still setting the ContentType header? And if so, are you sending JSON? If not, remove that header, as the service probably fails on trying to parse the input.
Wrikken
Hmm, if omitting content-type, and setting accept, still results in XML, I'd say there's a problem in the core of the webservice, but as I don't know ASP.NET, I couldn't tell you what or where unfortunately.
Wrikken
+2  A: 

Update 2:

I'm using fiddler2 to look at a successful POST request (from jquery to my asmx service), and I see a difference that might be worth checking:

Accept: application/json, text/javascript, */*

There's some other differences as well, but that one is the only one that leaps out as a possible smoking gun.

Updated Answer (in response to updated question):

It looks like you're using the contentStream correctly. However, the data you're pushing onto it ("aString=kjkjk") isn't valid JSON. As noted below, your data will likely need to be in valid JSON format:

{'aString':'kjkjk'}

Original Answer:

I believe you're setting the "aString" content incorrectly. For POST-method requests, the "payload" data isn't applied to the header, it is the content of the request itself. Therefore, you need to stream it onto the request object; see this MSDN reference for an example. Don't forget to also set the request's content-length.

Since you're implementing the service via JSON (and have specified JSON as the content-type), I believe you'll need to convert a JSON string to raw bytes, and that's what you'll push it onto the stream. Your JSON string should look something like this:

{'aString':'This is the text I want to echo.'}

You might need to do some fine-tuning (I'm not at a place where I can easily put together an exact code sample), but this should get you going in the right direction.

mikemanne
Still no luck.. Need a more specific answer
Oren A
One silly thing: make sure your URL (methodUrl) is targeting the correct webservice (htp://yourmachine/MyAPI.asmx/Echo). (deliberately misspelled 'http' so it would show up correctly in this comment)
mikemanne
Should be ashamed of myself (-:. Can't give you the bounty yet, only in 22 hours (SO rules). Thanks.
Oren A
The URL was the issue? That happens to every developer I've ever known (myself included) - you get so focused on the details and possible deeper causes, that it takes a fresh set of eyes to point out the obvious. :)
mikemanne
(-: No, the json was the issue, I was so sure ASP.NET will take care of that for me, I ignored it.
Oren A