views:

4440

answers:

4

I have the following code which works just fine when the method is "POST", but changing to "GET" doesn't work:

HttpWebRequest request = null;
request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
request.Method = "POST"; // Doesn't work with "GET"

request.BeginGetRequestStream(this.RequestCallback, null);

I get a ProtocolViolationException exception with the "GET" method.

Edit: After having a look using Reflector, it seems there is an explicit check for the "GET" method, if it's set to that it throws the exception.

Edit2: I've updated my code to the following, but it still throws an exception when I call EndGetResponse()

if (request.Method == "GET")
{
    request.BeginGetResponse(this.ResponseCallback, state);
}
else
{
    request.BeginGetRequestStream(this.RequestCallback, state);
}

In my function, ResponseCallback, I have this:

HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);

Which throws the exception as well.

Answer

The above code now works, I had forgotten to take out the Content-Type line which was causing the exception to be thrown at the end. +1 to tweakt & answer to Jon.

The working code is now below:

HttpWebRequest request = null;
request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "GET";// Supports POST too

if (request.Method == "GET")
{
    request.BeginGetResponse(this.ResponseCallback, state);
}
else
{
    request.BeginGetRequestStream(this.RequestCallback, state);
}
+2  A: 

Does it make sense for a GET request to send a Content-Type? Did you try removing the third line?

Mark Renouf
+3  A: 

This is specified in the documentation. Basically GET requests aren't meant to contain bodies, so there's no sensible reason to call BeginGetRequestStream.

Jon Skeet
OK, that's fine - how do I use the HttpWebRequest with the GET method? I really don't want to have 2 logic paths dependent on whether it's GET/POST (using WebClient for GET).
Mark Ingram
Only fetch the request stream if you've got a body. If you've got a body and you're making a GET request, your bug is elsewhere.
Jon Skeet
There's no body, but I do need to get the request stream, as I'm getting the result from a REST api.
Mark Ingram
Sorry, meant the response stream - I need to get the result from the server.
Mark Ingram
No, that means you need the *response* stream. The request stream is the body you send. With GET, you don't send a body.
Jon Skeet
Darn I hate collisions. Yes, you need the response stream. If you try to do it synchronously, do you still get the error?
Jon Skeet
Mark Ingram
OK, I've got the answer. Shall update post to reflect.
Mark Ingram
+1  A: 

BeginGetRequestStream is used to get a stream specifically for writing data to the request. This is not applicable to GET requests.

The documentation for the BeginGetRequestStream method states explicitly that the method will throw a ProtocolViolationException if the Method is GET or HEAD.

Morale: read the docs ;-)

Tor Haugen
A: 

It is specified in the documentation for the GetRequestStream that it will throw a ProtocolViolationException if the method is GET. However, I cannot find anything in the HTTP spec to suggest that this is actually an HTTP protocol violation. Consider this a challenge.

Mark