function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Longhorn94Longhorn94 

Bulk API from C#.net: Unable to Add Batch to Existing Job

Hello,

 

I'm trying to add a batch to an existing job using the Bulk API from C#.  I've created the job and can get info on it, but am running into a problem when attempting to add a batch of data to it.

 

Here's the code.  The problem is that at run time the call to this line never returns:

Stream datastream = request.GetRequestStream();

 

This only happens when the url on the request includes the "batch" at the end (see first line of code).  The JobID parameter is valid, is an open job, and works in a separate call to get info.

 

Does anyone know what the problem might be?

 

            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://na12-api.salesforce.com/services/async/23.0/job/" + JobID + "/batch");
            request.Method = WebRequestMethods.Http.Post;
            request.ContentType = "application/xml; charset=UTF-8";
            request.Headers.Add("X-SFDC-Session", _SessionID);
            request.KeepAlive = false;
            request.Host = "na12.salesforce.com";
            request.UserAgent = ".NET Framework Test Client";
            request.Accept = "application/xml";

            string body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> ";
            body += "<sObjects xmlns=\"http://www.force.com/2009/06/asyncapi/dataload\">";
            body += "  <sObject>";
            body += "    <description>Created from Bulk API on Wed Jan 4 2012</description>";
            body += "    <name>[Bulk API] Account 0 (batch 0)</name>";
            body += "  </sObject>";
            body += "  <sObject>";
            body += "    <description>Created from Bulk API on Wed Jan 4 2012</description>";
            body += "    <name>[Bulk API] Account 1 (batch 0)</name>";
            body += "  </sObject>";
            body += "</sObjects>";

            //Convert the body of request into a byte array
            byte[] byteArray = Encoding.UTF8.GetBytes(body);

            //Set the length
            request.ContentLength = byteArray.Length;

            //Write the body to the request by using a datastream
            //This line never returns....
            Stream datastream = request.GetRequestStream();
            datastream.Write(byteArray, 0, byteArray.Length);
            datastream.Close();

            //Call the service and get the response as a data stream
            WebResponse response = request.GetResponse();
            datastream = response.GetResponseStream();
            StreamReader reader = new StreamReader(datastream);
            string responseFromServer = reader.ReadToEnd();

            response.Close();

 

 

 

Longhorn94Longhorn94

I found the problem; when creating the job on an earlier call, I needed to set the contenttype to "XML".  It had been set to "CSV".

 

            string body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> ";
            body += "<jobInfo xmlns=\"http://www.force.com/2009/06/asyncapi/dataload\">";
            body += "<operation>insert</operation>";
            body += "<object>Account</object>";
            body += "<contentType>XML</contentType>";
            body += "</jobInfo>";

 

lane_cwelane_cwe

Hi,

Can you please share your code for creating a job? I received error message (400) Bad Request.

 

 private void CreateJob()
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://na2.salesforce.com/services/async/24.​0/job");
            request.Method = WebRequestMethods.Http.Post;
            request.ContentType = "application/xml; charset=UTF-8";
            request.Headers.Add("X-SFDC-Session", _SessionID);
            request.KeepAlive = false;
            request.Host = "na2.salesforce.com";
            request.UserAgent = ".NET Framework Test Client";
            request.Accept = "application/xml";
            
            string body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
            body += "<jobInfo xmlns=\"http://www.force.com/2009/06/asyncapi/dataload\">";
            body += "<operation>query</operation>";
            body += "<object>Account</object>";
            body += "<concurrencyMode>Parallel</concurrencyMode>";
            body += "<contentType>XML</contentType>";
            body += "</jobInfo>";

            byte[] byteArray = Encoding.UTF8.GetBytes(body);
            request.ContentLength = byteArray.Length;

            Stream datastream = request.GetRequestStream();
            datastream.Write(byteArray, 0, byteArray.Length);
            datastream.Close();

            WebResponse response = request.GetResponse(); //This line returns (400) Bad Request
            datastream = response.GetResponseStream();
            StreamReader reader = new StreamReader(datastream);
            string responseFromServer = reader.ReadToEnd();

            response.Close();
        }

 

Longhorn94Longhorn94

Try using this code to see more info about the error in the response - check in the responseFromServer string in the catch block.

 

            try
            {
                //Call the service and get the response
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                if (HttpStatusCode.OK == response.StatusCode)
                {
                    Stream dataStream = response.GetResponseStream();
                    StreamReader reader = new StreamReader(dataStream);
                    responseFromServer = reader.ReadToEnd();
                    response.Close();
                }
            }
            catch (WebException e)
            {
                using (WebResponse response = e.Response)
                {
                    HttpWebResponse httpResponse = (HttpWebResponse)response;
                    responseFromServer = string.Format("Error code: {0}  ", httpResponse.StatusCode);
                    using (Stream data = response.GetResponseStream())
                    {
                        responseFromServer += new StreamReader(data).ReadToEnd();
                        return responseFromServer;
                    }
                }
            }

 

 

lane_cwelane_cwe

Thank you Longhorn94. That helps.

NK123NK123

Hi Lane,

 

What did you do to resolve your issue with this line below:

Please let me know. I am getting the same issue.

 

Thanks,

NK

 

 WebResponse response = request.GetResponse(); //This line returns (400) Bad Request
Longhorn94Longhorn94

It could be different things, all of which just return the Bad Request response.

If you put in the exception handling above and step through it, you can see more details about the exception that's getting returned.  That should help you find the real problem and fix it.  Let me know if that helps...

NK123NK123

I have the code sample shown below:

When I run the line "request.GetRequestStream()" get called it takes long time before the control comes back to the program and then when this line "Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)" get executed, system is giving errors as shown below:

 

The underlying connection was closed: An unexpected error occurred on a receive.

StatusCode BadRequest {400} System.Net.HttpStatusCode
StatusDescription "Bad Request" String

 

For _SessionID, I am passing the session ID which I get by calling the login with Soap and then that session ID is passed to the code below as per documentation. 

For _ServerUrl, I tried to use my QA link: { https://tapp0-api.salesforce.com/services/async/25.​0/job}  as well as for prod:  {https://na6.salesforce.com/services/async/25.​0/job}

and in both cases I am getting the above error.

By the way the error handling is not getting executed since this "

If e.Response IsNot Nothing Then

is always returning nothing for e.Response.

 

Here is the code sample:

=============================

 

Dim request As HttpWebRequest = DirectCast(HttpWebRequest.Create(_ServerUrl), HttpWebRequest)
request.Method = WebRequestMethods.Http.Post
request.ContentType = "application/xml; charset=UTF-8"
request.Headers.Add("X-SFDC-Session", _SessionID)
request.KeepAlive = False
''request.Host = "na6.salesforce.com"
request.Host = "tapp0-api.salesforce.com"
request.UserAgent = ".NET Framework Test Client"
request.Accept = "application/xml"
Dim body As String = ""body += "<?xml version=""1.0"" encoding=""UTF-8""?>"
body += "<jobInfo xmlns=""http://www.force.com/2009/06/asyncapi/dataload"">"
body += "<operation>insert</operation>"
body += "<object>Account</object>"
body += "<contentType>CSV</contentType>"
body += "</jobInfo>"
Dim strErrorMessage As String = ""
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(body)
request.ContentLength = byteArray.Length
request.Timeout = 5000
ServicePointManager.ServerCertificateValidationCallback = New System.Net.Security.RemoteCertificateValidationCallback(AddressOf customXertificateValidation)
Try
Dim datastream As Stream = request.GetRequestStream()
datastream.Write(byteArray, 0, byteArray.Length)
datastream.Close()
Catch ex As Exception
strErrorMessage = ex.Message
End Try
 
Dim responseFromServer As String
Try
'Call the service and get the response
Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse) ''Failes on this line
If HttpStatusCode.OK = response.StatusCode Then
Dim dataStream2 As Stream = response.GetResponseStream()
Dim reader As New StreamReader(dataStream2)
responseFromServer = reader.ReadToEnd()
response.Close()
End If
request.Abort()
Catch e As WebException
If e.Response IsNot Nothing Then
Using response As WebResponse = e.Response
Dim httpResponse As HttpWebResponse = DirectCast(response, HttpWebResponse)
responseFromServer = String.Format("Error code: {0} ", httpResponse.StatusCode)
Using data As Stream = response.GetResponseStream()
responseFromServer += New StreamReader(data).ReadToEnd()
Return responseFromServer
End Using
End Using
End If
request.Abort()
End Try

 

 

=============================

ggManggMan

Hi Longhorn94,

 

I added your code for get  clear error. It's saying invalid Session. I used the session i created during the login.

This is the way I did.

 

 SforceService binding;

 string  _SessionID;

 

 LoginResult lr;

 lr = binding.login(userName, (pwd + _token));
  binding.SessionHeaderValue = new SessionHeader();
  binding.SessionHeaderValue.sessionId = lr.sessionId;

_SessionID = lr.sessionId;

 

can you please tell me what's the issue here


 
lane_cwelane_cwe

Try adding binding.Timeout and binding.Url

SforceService binding = new SforceService();
string _SessionID;
LoginResult lr;
binding.Timeout = 5000;
lr = binding.login(userName, (pwd + _token));
binding.Url = lr.serverUrl;
binding.SessionHeaderValue = new SessionHeader();
binding.SessionHeaderValue.sessionId = lr.sessionId;
_SessionID = lr.sessionId;

 

ggManggMan

Hi ,

 Thank your for advice.I changed the code as you said.

But still the error is coming  :( . Do you have any sample C# code for bulk API.

 

Thanks

 

ggManggMan
govindb1.396432156444516E12govindb1.396432156444516E12
Hi All,

Can anyone please tell me how should be my request body for creating a batch in CSV format.

Thanks in advance