0

I'm receiving a IFormFile object from an API POST request, and I'm trying to pass that file through to another API endpoint via a POST request with some JSON attached.

I am able to embed the image inside the request, but the server I'm sending to always returns a 500. I believe the issue the fact that I'm sending the JSON and the IFormFile together, as when I send one or the other it works okay (albeit, I'm not receiving the 200 response I want due to one or the other being missing).

Here is the code I'm using to post the data:

public async Task<APIResponse<T>> PostForm<T>(string baseURL, string apiName, IFormFile file, string jsonToPost = "", Dictionary<string, string> headers = null) where T : class
{
    using (var client = new HttpClient() { BaseAddress = new Uri(baseURL) })
    {
        client.BaseAddress = new Uri(baseURL);

        HttpResponseMessage response = null;
        if (headers != null)
        {
            foreach (var header in headers)
            {
                client.DefaultRequestHeaders.Add(header.Key, header.Value);
            }
        }

        try
        {
            var multiContent = new MultipartFormDataContent();
            var fileStreamContent = new StreamContent(file.OpenReadStream());
            multiContent.Add(fileStreamContent, "file", file.FileName);
            multiContent.Add(new StringContent(jsonToPost,System.Text.Encoding.UTF8, "application/json"));
            response = await client.PostAsync(apiName, multiContent);

            return new APIResponse<T>(JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync()), null, (int)response.StatusCode);
        }
        catch 
        {
            return new APIResponse<T>(null, await response.Content.ReadAsStringAsync(), (int)response.StatusCode);
        }

    }

}

And here is what the JSON looks like if it helps anyone:

{
  "orderId": 694532,
  "type": "4x6",
  "copies": 1,
  "sizing": "Crop",
  "priceToUser": 4000,
  "md5hash": "5fed252e505f8542b38d9c0b1f221a71"
}

Edit - Updated code:

public async Task<APIResponse<T>> PostForm<T>(string baseURL, string apiName, IFormFile file, string jsonToPost = "", Dictionary<string, string> headers = null) where T : class
{
    var client = new HttpClient();
    client.BaseAddress = new Uri(baseURL);

    HttpResponseMessage response = null;
    if (headers != null)
    {
        foreach (var header in headers)
        {
            client.DefaultRequestHeaders.Add(header.Key, header.Value);
        }
    }

    try
    {
        var multiContent = new MultipartFormDataContent();
        multiContent.Add(new StringContent(jsonToPost,System.Text.Encoding.UTF8, "application/json"));
        multiContent.Add(GetByteArray(file), "file", file.FileName);

        response = await client.PostAsync(apiName, multiContent);

        return new APIResponse<T>(JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync()), null, (int)response.StatusCode);
    }
    catch 
    {
        return new APIResponse<T>(null, await response.Content.ReadAsStringAsync(), (int)response.StatusCode);
    }

}

private ByteArrayContent GetByteArray(IFormFile file){
    byte[] data;

    var br = new BinaryReader(file.OpenReadStream());
    data = br.ReadBytes((int)file.OpenReadStream().Length);

    return new ByteArrayContent(data);
}
spogebob92
  • 1,334
  • 3
  • 22
  • 30
  • `HttpClient` should not be in a `using`. What does the definition of the api your posting to look like? – JSteward Mar 06 '18 at 21:52
  • Oh interesting, pretty new to .net - here are the docs for that call http://pwinty.com/api/#photos-create – spogebob92 Mar 06 '18 at 21:53
  • I don't see anything matching your JSON object in the docs. Which endpoint are you posting to? – JSteward Mar 06 '18 at 21:58
  • If your posting to `Add photo to order`; can you post what your complete request looks like? – JSteward Mar 06 '18 at 22:11
  • `{Method: POST, RequestUri: 'https://sandbox.pwinty.com/v2.6/Orders/694532/Photos', Version: 1.1, Content: System.Net.Http.MultipartFormDataContent, Headers: { X-Pwinty-MerchantId: X-Pwinty-REST-API-Key: Content-Type: multipart/form-data; boundary="1517ca59-8cec-47af-8b14-b4bd859e4e49" Content-Length: 18885 }}` – spogebob92 Mar 06 '18 at 22:20
  • Shot in the dark, how about trying `ByteArrayContent` instead of `StreamContent` for the file [like here](https://stackoverflow.com/a/19983672/7339946) – JSteward Mar 06 '18 at 22:24
  • I've updated the code, added a method which returns a `ByteArrayContent` from the `IFormFile` (which contains data I've checked) - still the same result – spogebob92 Mar 06 '18 at 22:35
  • I'm not seeing much help in the docs. My only thought would be to wrap your `BinaryReader` in a using so it flushes the stream before trying to send to the api. Other than that it might be time to engage [pwinty support](http://support.pwinty.com/support/home) – JSteward Mar 07 '18 at 16:00

0 Answers0