HttpWebRequest and the Expect: 100-continue Header Problem

Apparently I’m not the only one to run into this annoying problem. When using the HttpWebRequest to POST form data using HTTP 1.1, it ALWAYS adds the following HTTP header "Expect: 100-Continue". Fixing the problem has proved to be quite elusive.

According to the HTTP 1.1 protocol, when this header is sent, the form data is not sent with the initial request. Instead, this header is sent to the web server which responds with 100 (Continue) if implemented correctly. However, not all web servers handle this correctly, including the server to which I am attempting to post data. I sniffed the headers that Internet Explorer sends and noticed that it does not send this header, but my code does.

Looking through the newsgroups, several people have had problems with this, but nobody with a solution (apart from going back to HTTP 1.0 which doesn’t work for me).

At this point, I thought I would fire up Lutz Roeder’s Reflector 4.0 and look through the source code for the System.Net.HttpWebRequest class. Aha! There it is. Within a private method named "MakeRequest()" are the following lines of code:

if (this._ExpectContinue && ((this._HttpWriteMode == HttpWriteMode.Chunked) || (this._ContentLength > ((long) 0))))
{
    this._HttpRequestHeaders.AddInternal("Expect", "100-continue");
}

So even if you try to remove the Expect header from the _HttpRequestHeaders collection, the header will get added back when the request is actually made.

Unfortunately, fixing this is not easy since MakeRequest is a private method. Walking up the callee graph, I found that the method I would have to override is BeginGetRequestStream (there are other ancestors aside from this one). Unfortunately this method relies on several internal and private objects to which I do not have access. I hoped to re-use the existing code base and only make a slight tweak.

I even started down the path of building my own HttpWebRequest class using the Rotor source code but ran into several problems there as well.

In any case, I think the easiest way to get this fixed is to find the right person at Microsoft and ask them very nicely to try to get this in SP2. Pretty Please?

UPDATE: Lance Olson points me to the solution in my comments section. The System.Net.ServicePointManager class has a static property named Expect100Continue. Setting this to false will stop the header "Expect: 100-Continue" from being sent. Thanks Lance!!!

What others have said

Requesting Gravatar... dk May 15, 2004 3:45 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
dude that happens to me all.....the time.
Requesting Gravatar... nospamplease75@yahoo.com (Haacked) May 15, 2004 4:20 PM
# RE: HttpWebRequest and the Expect: 100-continue Header Problem
DK, this post wasn't for you. ;) I need some real answers!
Requesting Gravatar... Koba May 15, 2004 6:01 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Happiness is not getting what you want, it's wanting what you have.
Requesting Gravatar... Lance Olson Jun 02, 2004 10:57 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
You can turn off the HttpWebRequest 100 continue behavior using the System.Net.ServicePointManager.Expect100Continue property.

-Lance
Requesting Gravatar... S Jun 28, 2004 5:01 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Lance, after struggling with .NET SOAP POST'ing through an ISA proxy (which seems to be blocking the 100 Continue response, possibly that's configurable somewhere, but I haven't got access), this was exactly what I needed. Thanks!
Requesting Gravatar... Michael Jan 20, 2005 9:15 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
This worked well for me. Thanks for the help.
Requesting Gravatar... tonyg Feb 23, 2005 1:14 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Sadly, setting a global variable is a real non-solution if you're writing library code. What if the library's client application needs to use 100-continue for something? They're basically completely out of luck. (The situation gets worse if the client is multithreaded.)

So of the two possible options, (1) set a global variable and (2) downgrade to HTTP/1.0, neither are really very clever ways of doing things.

Clearly the correct thing is for the .NET libraries to allow setting Expect100Continue for *each* *request* in a thread-safe and library-writer-friendly manner, not using a global variable.
Requesting Gravatar... Haacked Feb 23, 2005 5:37 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
That's a very good point TonyG.
Requesting Gravatar... Josh Pollard Mar 18, 2005 11:10 AM
# Yellow Rate Quote Web Service Changed
Requesting Gravatar... Miracle Mar 31, 2005 9:58 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
We have the same issue also, glad to see this thread... however we don't know where should we place the code (ServicePointManager.Expect100Continue = false;) in our ASP.NET application.

Can someone help? Thanks.
Requesting Gravatar... Haacked Mar 31, 2005 10:10 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
That's a static property, so place the call somewhere that you know will execute before your http request code does. For example you could set it just before your http request. Or you could put it in a static constructor.
Requesting Gravatar... ben Apr 20, 2005 3:07 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
thanks mate, exactly our problem too and worked perfectly for us
Requesting Gravatar... Mirronelli Jun 02, 2005 6:22 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Hi,

I think I found a bit better solution. Thanks to this thread I started reading all around the internet and have found out this:

The servicepointmanager is something like a http connection pool. It creates new servicepoints whenever needed and sets their Expect100Continue property based on its own static Expect100Continue value.

This means if a servicepoint was created before changing servicepointmanagers Expect100Continue property it preserves its original value.

The point is you can always change the servicepoints Expect100Continue instance property, thus changing the behaviour of each individual request.

The WebRequest class provides its underlying servicepoint so you can change it right before the request is being made.

Example:
// create web request
HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create("http://something");
webRequest.Method = "POST";
webRequest.ServicePoint.Expect100Continue = false;

// post data
requestStream = webRequest.GetRequestStream();
StreamWriter requestWriter = new StreamWriter(requestStream);
requestWriter.Write(dataToPost);
requestWriter.Close();

//wait for server response
HttpWebResponse response = (HttpWebResponse) webRequest.GetResponse();
Requesting Gravatar... IvanX Apr 02, 2006 9:10 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Thanks for writing this. I thought it was just me! I was excited to see there was an easy solution. Frustratingly, however, the Expect100Continue property of WebRequest.ServicePoint is absent in .NET Compact Framework, which is what I am working with. I might just have to go with raw sockets for posting if I can't figure something else out...
Requesting Gravatar... REvol May 18, 2006 8:27 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
This thread is a great help! I encountered the 417: Expectation Failed problem too, and the description from the message is just that much. There was no way for me to derive the actual solution without the help from this thread.

Can't they provide a more descriptive message to help pin point the issue?

Anyway, thanks.
Requesting Gravatar... aaron Jul 25, 2006 1:23 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
didnt help YET but its getting me somewhere, thanks for the post
Requesting Gravatar... Michael Freidgeim Sep 13, 2006 1:22 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Thanks for the post. It helped me to fight with Squid proxy server(see my post http://geekswithblogs.net/mnf/archive/2006/09/13/91012.aspx).
Also could you change your link Expect100Continue to point to MSDN2(http://msdn2.microsoft.com/en-us/library/system.net.servicepoint.expect100continue.aspx).
MSDN Link Expect100Continue has notice "supported only in version 1.1", which can be interpreted as obsolete.
Requesting Gravatar... XCRYX Oct 03, 2006 2:45 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Hello guys. I have a site that drives me crazy. I want to make a post in there from a WinApp in C# but everytime I tried, had no luck.
The website is: http://patrick.net/housing/news.php but you can see that it redirects you at http://patrick.net/housing/login.php which requires an email and a password first.
When you try a request with ie browser is something like this: email=xcrysoft@hotmail.com&pw=xxxxx&submit=Log+In Everytime I post with my app I receive as response the same login.php and no news.php that I want. This are the header from the request from my app:

Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Cache-Control: no-cache
Accept-Encoding: gzip, deflate
Content-Length: 59
Connection: Keep-Alive
Host: patrick.net

So, I managed to get rid of the 100-continue thing thanks to this thread... but still have this problem. Can anybody help me? PLEASE!!! I can tell you in details if someone wants to help me
Requesting Gravatar... eeichinger Oct 16, 2006 2:57 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Hi,

There's also an undocumented configuration setting for this:

<configuration>
<system.net>
<settings>
<servicePointManager
checkCertificateName="true"
checkCertificateRevocationList="false"
useNagleAlgorithm="true"
expect100Continue="false"
/>

<httpWebRequest
maximumResponseHeadersLength="64"
useUnsafeHeaderParsing="false"
/>
</settings>
</system.net>
</configuration>

Requesting Gravatar... John Mencias Nov 22, 2006 8:00 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
You helped me too! Thanks.
Requesting Gravatar... Pavel Nov 23, 2006 12:55 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Very nice describtion, anyways, I've set the property (Expect100Continue) to false and I'm still getting the time out exception...
Could this be just because of the connection? I mean, that a simple time out occures due to the slow connection?
Increasing the time out property seems to help...

Any ideas?
Requesting Gravatar... Kin Mar 08, 2007 2:40 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Whoah...
thanks alot for writing this topic...
its problem nearly make me hang my self... :))
now my uploader work fine...

Thanks again!

Regards
Kin
Requesting Gravatar... Chris Martin Mar 16, 2007 9:40 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Holy shit!

I found this post whilst searching for POST timeout and thought it was a long shot for my problem. Well, it worked for me!

Thank you so much!!!
Requesting Gravatar... Latest Newsgroup Posts May 09, 2007 4:14 AM
# Re: Http request problem
At [link] , the suggested fix is: [System.Net.ServicePointManage r]::Expect100Continue = $false
Requesting Gravatar... AJB May 16, 2007 6:43 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Has anyone been able to resolve this issue using this fix? I have the exact same problem and it appears as though the fix did nothing.

Before initializing my httpwebrequest objects, I did:
ServicePointManager.Expect100Continue = False;

Then, after my variable declaration, I did:

myRequest.ServicePoint.Expect100Continue = false;

Still, it times out on getresponse().

Ideas?
Requesting Gravatar... coollil7 May 17, 2007 6:44 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Hi all,
Thanks for this helpful forum. I've been facing the problem of POST for a long time. Now i have tried disabling the Expect100Continue. But I'm having another error now. It says :
Server error in '/melatWSite' application: the state information is invalid for this page and might be corrupted.

melatWSite is my ASP.NET Web application.

I have a Proxy build in C# and i'm trying to access my own created web application from this developed proxy. When it receives GET messages it works but with POST it does.
Can anyone help me in this please, cause i'm really stuck.

Tnks in advance
Requesting Gravatar... Sunil Rashinkar Jun 01, 2007 2:38 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
I have done the following....but i havent tested it yet...cause i was not sure if this is the right place to do the change...

A Snip of my exisiting entries in "web.config" file in
directory "C:\WINNT\Microsoft.NET\Framework\v2.0.50727\CONFIG" for <system.net>
<system.net>
<defaultProxy>
<proxy usesystemdefault="true" />
</defaultProxy>
</system.net>

I updated it with the following in the "web.config" file and it looks like below:
<system.net>
<defaultProxy>
<proxy usesystemdefault="true" />
</defaultProxy>
<settings>
<servicePointManager checkCertificateName="true" checkCertificateRevocationList="false" useNagleAlgorithm="true" expect100Continue="false"/>
<httpWebRequest maximumResponseHeadersLength="64" useUnsafeHeaderParsing="false"/>
</settings>
</system.net>

Is this correct?

Sunil Rashinkar
Requesting Gravatar... Sunil Rashinkar Jun 01, 2007 2:38 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
I have done the following....but i havent tested it yet...cause i was not sure if this is the right place to do the change...

A Snip of my exisiting entries in "web.config" file in
directory "C:\WINNT\Microsoft.NET\Framework\v2.0.50727\CONFIG" for <system.net>
<system.net>
<defaultProxy>
<proxy usesystemdefault="true" />
</defaultProxy>
</system.net>

I updated it with the following in the "web.config" file and it looks like below:
<system.net>
<defaultProxy>
<proxy usesystemdefault="true" />
</defaultProxy>
<settings>
<servicePointManager checkCertificateName="true" checkCertificateRevocationList="false" useNagleAlgorithm="true" expect100Continue="false"/>
<httpWebRequest maximumResponseHeadersLength="64" useUnsafeHeaderParsing="false"/>
</settings>
</system.net>

Is this correct?

Sunil Rashinkar
Requesting Gravatar... David Grant Jun 08, 2007 11:51 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Jesus Christ, thanks for the solution.
Requesting Gravatar... henk de bakker Aug 22, 2007 5:54 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Thanks, saved me a lot of time.
Requesting Gravatar... sg Aug 22, 2007 3:43 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
System.Net.ServicePointManager.Expect100Continue

Worked for us too!
Requesting Gravatar... IBR Sep 15, 2007 12:57 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Thanks man the error 417 error no longer appear, but when i post the login data to the form the form didn't login?????
HELP PLEASE
Requesting Gravatar... SC Jan 23, 2008 11:02 PM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
According to the HTTP 1.1. RFC...
http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html
... it is not recommended the client wait long before sending the the request body if it does not receive a suitable response (eg. if the server is HTTP 1.0).

---------
Because of the presence of older implementations, the protocol allows ambiguous situations in which a client may send "Expect: 100- continue" without receiving either a 417 (Expectation Failed) status or a 100 (Continue) status. Therefore, when a client sends this header field to an origin server (possibly via a proxy) from which it has never seen a 100 (Continue) status, the client SHOULD NOT wait for an indefinite period before sending the request body.
Requesting Gravatar... kotopyos Jul 02, 2008 7:14 AM
# re: HttpWebRequest and the Expect: 100-continue Header Problem
Thank U very much! Very useful article

What do you have to say?

(will show your gravatar)
Please add 1 and 5 and type the answer here: