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
Frantz  CarionFrantz Carion 

C# Bulk API Unable to parse job

Hi all,
I'm currently trying to code an upload facility to salesforce using the Bulk API, however my efforts are in vain so far as i keep getting error 400 Bad Request InvalidJob Unable to Parse job when running the post request to create the job.

I believe, thx to another post i could see, that this is due to the URL use to parse the request that is not correct. In my case, i've tried with https://emea.salesforce.com/services/async/30.0/job

this is based on the instance i get from connecting through the SOAP Api's loginresult serverURL and the API Version showing in my WDSL Partenr file. I've seen sites that mentions emea.salesforce.com maps to eu0-api.salesforce.com when using API, but oddly enough when trying with this i encounter the exact same error.

here below the code i'm using to try to add a job entry and parse the web request

private static string AddJob(SforceService binding, string sOperation, string sObjectName)
        {
            string str = "", reqURL = "";
            byte[] bytes = null;
            XmlDocument reqDoc = null;
            XmlDocument responseXmlDoc = new XmlDocument();

            str = "" 
                + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
                + "<jobInfo xmlns=\"http://www.force.com/2009/06/asyncapi/dataload\">"
                + "   <operation></operation>"
                + "   <object></object>"
                + "   <contentType>CSV</contentType>"
                + "</jobInfo>";

            reqURL = "https://eu0-api.salesforce.com/services/async/30.0/job";
            reqDoc = new XmlDocument();
            reqDoc.LoadXml(str); 

            //xml modifications
            reqDoc.GetElementsByTagName("operation")[0].InnerText = sOperation;
            reqDoc.GetElementsByTagName("object")[0].InnerText = sObjectName;
            bytes = System.Text.Encoding.ASCII.GetBytes(reqDoc.InnerXml);

            using (Stream respStream = Post(bytes, reqURL, binding.SessionHeaderValue.sessionId, "POST", "text/csv; charset=UTF-8"))
            {
                responseXmlDoc.Load(respStream);
                string sJobId = (responseXmlDoc != null ? responseXmlDoc.GetElementsByTagName("id")[0].InnerText : "");
                return sJobId;
            }
        }

private static Stream Post(byte[] bytes, string reqURL, string sSessionId, string sMethod, string sContentType)
        {
            WebRequest req = WebRequest.Create(reqURL);
            req.Method = sMethod;
            req.ContentType = sContentType;
            req.Headers.Add("X-SFDC-Session: " + sSessionId);

            if (bytes != null)
            {
                req.ContentLength = bytes.Length;
                System.IO.Stream strmHttpContent = req.GetRequestStream();
                strmHttpContent.Write(bytes, 0, bytes.Length);
                strmHttpContent.Close();
            }

            string sServerResponse;
            WebResponse resp = null;

            try
            {
                resp = req.GetResponse();

                if (((HttpWebResponse)resp).StatusCode == HttpStatusCode.OK)
                {
                    Stream dataStream = resp.GetResponseStream();
                    StreamReader reader = new StreamReader(dataStream);
                    sServerResponse = reader.ReadToEnd();
                    resp.Close();
                }
            }
            catch (WebException ex)
            {
                using (WebResponse errorresp = ex.Response)
                {
                    HttpWebResponse httpresp = (HttpWebResponse)errorresp;
                    sServerResponse = string.Format("Error code: {0} ", httpresp.StatusCode);

                    using (Stream data = errorresp.GetResponseStream())
                    {
                        sServerResponse += new StreamReader(data).ReadToEnd();
                    }
                }
            }

            return resp.GetResponseStream();
        }

i would be grateful if any of you could guide me on this as i've been searching extensively all day with no progress so far.

AshwaniAshwani
You have to set endpoint of your Salesforce organisation instance not the eu0-api like. Instance would seems like: https://na17.salesforce.com/services/async/31.0/job and content-type must be "application/xml". 

Session Id and server URL are obtained when you login through SOAP API. I can't see that you are logged in.





Frantz  CarionFrantz Carion
as i mentioned in my previous post, prior to this i'm connecting through the SOAP API and retrieving both the session id and the instance name (again as i mentioned, the serverURL returned in the loginresult is emea, which never appears in the Bulk API examples i've seen so far).
As for the content type, again most examples i've seen shows text/csv. I'll follow your advise and try with application/xml (not sure i've tried that yet) and will let you know if that helped.

Frantz  CarionFrantz Carion
as advised, i've just tried passing "application/xml" to the post call from the AddJob method but that gave me the exact same error Unable to Parse Job (as suggested i also reverted to use the exact same instance name (emea) as given by the loginresult.serverURL, and therefore used the following request URL:
https://emea.salesforce.com/services/async/31.0/job)
Frantz  CarionFrantz Carion
ok, i've made some progress and identified the cause of this BadRequest error: the operation should be written in lower case and i had it capitalized.

I can therefore now create the job and batch correctly however i'm encountering an issue when the batch gets processed as i get "InvalidBatch : Field name not found : Id". I've specificed fieldnames in the csv file as they are named in Salesforce.
However i can not get to understand how the field used to match (since i'm trying to run an update here) the existing record is specified. Should it be prefixed by ReportTo?