0

I am sending up this payload

--BOUNDARY
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name="job"
{"columnDelimeter":",","contentType":"CSV","lineEnding":"\r\n","object":"Account","operation":"insert"}
--BOUNDARY
Content-Type: text/csv; charset=utf-8
Content-Disposition: form-data; name="content"; filename="content"; filename*=utf-8''%22content%22
TmFtZQ0KRHJ1bW1pbiBBY2NvdW50DQpMdW1taW4gQWNjb3VudA0K
--BOUNDARY--

Sending it to https://cs30.salesforce.com/services/data/v44.0/jobs/ingest

Im using C# here is my code

request.Method = method;
//request.ContentType = "application/json";
request.ContentType = "multipart/form-data; boundary=BOUNDARY";
request.Accept = "application/json";
request.Headers.Add("Authorization", "Bearer " + this.AccessToken);

if (!string.IsNullOrWhiteSpace(body))
{
    UTF8Encoding encoding = new UTF8Encoding();
    byte[] data = encoding.GetBytes(body);
    request.ContentLength = data.Length;
    using (var newStream = request.GetRequestStream())
    {
        newStream.Write(data, 0, data.Length);
        newStream.Flush();
    }
}

using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    if (response != null)
    {
        Stream responseStream = response.GetResponseStream();
        if (responseStream != null)
            using (StreamReader reader = new StreamReader(responseStream))
            {
                string result = reader.ReadToEnd();
                return string.IsNullOrWhiteSpace(result) ? null : result[0] == '{' ? (JContainer)JObject.Parse(result) : (JContainer)JArray.Parse(result);
            }
    }
}
}

I keep getting a 400 bad request, what am i missing?

0

So after struggling to make this work I was finally able to solve this, Most of my problems stem from my request object. Here's what I learned

Make sure the columnDelimeter and lineEnding are not the literal characters but the string value they set {BACKQUOTE,CARET,COMMA,PIPE,SEMICOLON,TAB} & {LF,CRLF}.

The Payload or Content is not in base64encoding when you send it up, although its very misleading from the documentation send up the content in plain text, however make sure you are setting proper lineEnding for the csv with the request.

--BOUNDARY Content-Type: application/json; charset=utf-8 Content-Disposition: form-data; name="job"

{"columnDelimiter":"COMMA","contentType":"CSV","lineEnding":"CRLF","object":"Account","operation":"insert"}

--BOUNDARY Content-Type: text/csv; charset=utf-8 Content-Disposition: form-data; name="content"; filename="content"; filename*=utf-8''%22content%22

"Name","ParentId","RecordTypeId","Product_Line_Lookup__c" "Drummin Account","001n000000SmDrC","012n00000000kkA","a0Ii000000oeJGP"

--BOUNDARY--

Here is the code I used for creating the form in C#.. there's other documentation you can find on the web but this pertains to this particular solution in C#


How I created the multipart form

private MultipartFormDataContent CreateMultiPartForm(BatchPayload payload, string boundary = "BOUNDARY")
{
    var form = new MultipartFormDataContent($"{boundary}");
    // Add First Region
    form.Add(new StringContent($"{Newtonsoft.Json.JsonConvert.SerializeObject(this.request)}{Environment.NewLine}", Encoding.UTF8, "application/json"), "\"job\"");
    form.Add(new StringContent(payload.ToString(), Encoding.UTF8, "text/csv"), "\"content\"", "\"content\"");
    return form;
}

Here is the BatchPayload Object it uses

public class BatchPayload : IDisposable
{
    // Track whether Dispose has been called.
    private bool disposed = false;
    public byte[] payload;

    public void Dispose()
    {
        GC.Collect();
    }

    public override string ToString()
    {
        //return Convert.ToBase64String(payload);
        return Encoding.Default.GetString(payload);
    }
}

And Finally for good measure my Request

public JobResponse SendMultiPartFormJob(BatchPayload payload)
{
    var form = CreateMultiPartForm(payload);
    try
    {
        var sbody = form.ReadAsStringAsync().Result;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        HttpWebRequest request = WebRequest.Create($"{this.auth.InstanceUrl}{this.JobURI}") as HttpWebRequest;
        if (request != null)
        {
            request.Method = HttpMethod.Post.Method;          
            request.ContentType = "multipart/form-data; boundary=BOUNDARY";
            request.Accept = "application/json";
            request.Headers.Add("Authorization", "Bearer " + this.auth.AccessToken);

            if (!string.IsNullOrWhiteSpace(sbody))
            {
                ASCIIEncoding encoding = new ASCIIEncoding();
                byte[] data = encoding.GetBytes(sbody);
                request.ContentLength = data.Length;
                using (var newStream = request.GetRequestStream())
                {
                    newStream.Write(data, 0, data.Length);
                    newStream.Flush();
                }
            }

            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                if (response != null)
                {
                    Stream responseStream = response.GetResponseStream();
                    if (responseStream != null)
                        using (StreamReader reader = new StreamReader(responseStream))
                        {
                            string result = reader.ReadToEnd();
                            this.response = Newtonsoft.Json.JsonConvert.DeserializeObject<JobResponse>(result);
                            return this.response;
                        }
                }
            }
        }

        return null;
    }
    catch (Exception ex)
    {
        throw;
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.