You need to sign in to do that
Don't have an account?
HTTP 400 on POST request
I am trying to use a post request to start a batch upsert. I have managed to get this to work using Curl, but I always get a 400 Bad Response when using the native HttpWebRequest method
I am passing the postData as UTF-8 encoded, and include the following for the contentType and headers
Content-Type: application/xml; charset=UTF-8
X-SFDC-Session: 00D700000008rXl!AQMAQA1rjn2jPYeSQuRoChquzvncucoqSNHVSUydo1eM0eSV3PKmSYE0QoD8gkSxBb2tuaT3wd8Dd1fr_YahMGhtxYO7m7u2
Below is the code; when I look at the request that works with Curl and my request in tcpTrace, they look identical.
public static string PostData(string url, byte[] postData, string contentType, KeyValuePair<string, string>[] headers, ITaskProgress progress)
{
int length = postData.Length;Uri uri = new Uri(url);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);request.Method = "POST";request.ServicePoint.Expect100Continue =
false;request.ContentType = contentType;
request.ContentLength = length;
request.ReadWriteTimeout = Timeout;
request.Timeout = Timeout;
request.AllowWriteStreamBuffering = false;request.Accept = "application/xml";request.UserAgent =
"Salesforce Web Service Connector"; if (headers != null){
foreach (KeyValuePair<string, string> header in headers)request.Headers.Add(header.Key, header.Value);
}
if (progress != null)progress.CurrentTaskProgress = 0;
using (Stream writeStream = request.GetRequestStream()){
int bytesSent = 0; while (bytesSent < length){
int bytesToSend = Math.Min(ChunkSize, length - bytesSent);writeStream.Write(postData, bytesSent, bytesToSend);
bytesSent += bytesToSend;
if (progress != null)progress.CurrentTaskProgress = (int)((long)bytesSent * 100) / length;}
}
if (progress != null)progress.CurrentTaskProgress = 100;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
...
Here is the actual post sent
POST /services/async/18.0/job HTTP/1.1
Content-Type: application/xml; charset=UTF-8
Accept: application/xml
User-Agent: Salesforce Web Service Connector
X-SFDC-Session: 00D700000008rXl!AQMAQA1rjn2jPYeSQuRoChquzvncucoqSNHVSUydo1eM0eSV3PKmSYE0QoD8gkSxBb2tuaT3wd8Dd1fr_YahMGhtxYO7m7u2
Host: localhost:8080
Content-Length: 626
Connection: Keep-Alive
<?xml version="1.0" encoding="utf-8"?><jobInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.force.com/2009/06/asyncapi/dataload"> <operation>upsert</operation> <object>Leads</object> <contentType>CSV</contentType> <numberBatchesQueued>0</numberBatchesQueued> <numberBatchesInProgress>0</numberBatchesInProgress> <numberBatchesCompleted>0</numberBatchesCompleted> <numberBatchesFailed>0</numberBatchesFailed> <numberBatchesTotal>0</numberBatchesTotal> <numberRecordsProcessed>0</numberRecordsProcessed> <numberRetries>0</numberRetries></jobInfo>
Very very strange
Hi Simon,
I did as you suggested and pulled the exact response coming back from salesforce using TCPTrace (having worked out that I can send to http as well as https, otherwise things get a bit mangled)
This is what I got back
HTTP/1.1 400 Bad Request
Via: 1.1 APTWARISA
Connection: Keep-Alive
Proxy-Connection: Keep-Alive
Transfer-Encoding: chunked
Date: Thu, 25 Mar 2010 08:45:21 GMT
Content-Type: application/xml
Server:
00de
<?xml version="1.0" encoding="UTF-8"?><error
xmlns="http://www.force.com/2009/06/asyncapi/dataload">
<exceptionCode>InvalidJob</exceptionCode>
<exceptionMessage>Unable to find object: Leads</exceptionMessage>
</error>
0
So I am getting back exactly the same as CUrl, but dotnet is consuming the problem by throwing an exception on the 400 Bad Request
Thanks for the help on this,
SImon
All Answers
Hi Simon,
I did as you suggested and pulled the exact response coming back from salesforce using TCPTrace (having worked out that I can send to http as well as https, otherwise things get a bit mangled)
This is what I got back
HTTP/1.1 400 Bad Request
Via: 1.1 APTWARISA
Connection: Keep-Alive
Proxy-Connection: Keep-Alive
Transfer-Encoding: chunked
Date: Thu, 25 Mar 2010 08:45:21 GMT
Content-Type: application/xml
Server:
00de
<?xml version="1.0" encoding="UTF-8"?><error
xmlns="http://www.force.com/2009/06/asyncapi/dataload">
<exceptionCode>InvalidJob</exceptionCode>
<exceptionMessage>Unable to find object: Leads</exceptionMessage>
</error>
0
So I am getting back exactly the same as CUrl, but dotnet is consuming the problem by throwing an exception on the 400 Bad Request
Thanks for the help on this,
SImon
For the record, I had to catch the Exception, and then continue to read from response stream within the WebException class
try
{
using (HttpWebResponse response = (HttpWebResponse) request.GetResponse()){
using (Stream responseStream = response.GetResponseStream()){
using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8)){
return readStream.ReadToEnd();}
}
}
}
catch(WebException webException){
using (Stream responseStream = webException.Response.GetResponseStream()){
using (StreamReader streamReader = new StreamReader(responseStream)){
return streamReader.ReadToEnd();}
}
}
I didn't know you could do that!
Very nice...