Async POST request in C# .NET

34,918

Solution 1

Main problem was probably coming from the fact i was mixing string and file data.

This solved it:

    public async Task<bool> CreateNewData (Data nData)
    {
        APIResponse serverReply;

        MultipartFormDataContent form = new MultipartFormDataContent ();

        form.Add (new StringContent (_partnerKey), "partnerKey");
        form.Add (new StringContent (UserData.Instance.key), "key");
        form.Add (new StringContent (nData.ToJson ()), "erList");

        if (nData._FileLocation != null) {
            string good_path = nData._FileLocation.Substring (7); // Dangerous
            byte[] PictureData = File.ReadAllBytes (good_path);
            HttpContent content = new ByteArrayContent (PictureData);
            content.Headers.Add ("Content-Type", "image/jpeg");
            form.Add (content, "picture_0", "picture_0");
        }

        form.Add (new StringContent (((int)(DateTime.Now.ToUniversalTime () -
            new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds).ToString ()), "time");
        serverReply = await MakePostRequest (_baseURL + "Data-report/create", form);

        if (serverReply.Status == SERVER_OK)
            return (true);
        Android.Util.Log.Error ("MyApplication", serverReply.Response);
        return (false);
    }

    private async Task<APIResponse> MakePostRequest (string RequestUrl, MultipartFormDataContent Content)
    {
        HttpClient httpClient = new HttpClient ();
        APIResponse serverReply = new APIResponse ();

        try {
            Console.WriteLine ("MyApplication - Sending Request");
            Android.Util.Log.Info ("MyApplication", " Sending Request");
            HttpResponseMessage response = await httpClient.PostAsync (RequestUrl, Content).ConfigureAwait (false);
            serverReply.Status = (int)response.StatusCode;
            serverReply.Response = await response.Content.ReadAsStringAsync ();
        } catch (HttpRequestException hre) {
            Android.Util.Log.Error ("MyApplication", hre.Message);
        }
        return (serverReply);
    }

Mainly using Multipart Content, setting the Content Type and going through a byte array seem to have done the job.

Solution 2

Do you need to send the data as a base64-encoded string? If you're sending arbitrary bytes (i.e., a photo), you can send them unencoded, if you use the ByteArrayContent class:

private async Task<APIResponse> MakePostRequest(string RequestUrl, byte[] Content)
{
    HttpClient  httpClient = new HttpClient();
    HttpContent httpContent = new ByteArrayContent(Content);
    APIResponse serverReply = new APIResponse();

    try {
        Console.WriteLine("Sending Request: " + RequestUrl + Content);
        HttpResponseMessage response = await httpClient.PostAsync(RequestUrl, httpContent).ConfigureAwait(false);
        // do something with the response, like setting properties on serverReply?
    }
    catch (HttpRequestException hre)
    {
        Console.WriteLine("hre.Message");
    }

    return (serverReply);
}
Share:
34,918
MagiKruiser
Author by

MagiKruiser

Updated on April 12, 2020

Comments

  • MagiKruiser
    MagiKruiser about 4 years

    I'm trying to upload a data over network using HttpClient / HttpContent However I can't seem to find a proper way to send a file this way.

    Here is my current code:

        private async Task<APIResponse> MakePostRequest(string RequestUrl, string Content)
        {
            HttpClient  httpClient = new HttpClient();
            HttpContent httpContent = new StringContent(Content);
            APIResponse serverReply = new APIResponse();
    
            httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            try {
                Console.WriteLine("Sending Request: " + RequestUrl + Content);
                HttpResponseMessage response = await httpClient.PostAsync(RequestUrl, httpContent).ConfigureAwait(false);
            }
            catch (HttpRequestException hre)
            {
                Console.WriteLine("hre.Message");
            }
            return (serverReply);
        }
    

    Content is a string of that form: paramname=value&param2name=value&param3name=value.. Point is that I have to actually send a file (photo) over this request.

    It seems to work fine for each parameters but the file itself (I have to send two authentification keys in the post request, and they are recognized)

    I proceed this way to retreive the picture as a string which might be one of the main reason it fails ? :/

        byte[] PictureData = File.ReadAllBytes(good_path);
        string encoded = Convert.ToBase64String(PictureData);
    

    Am I doing anything wrong ? Is there another and better way to create a proper POST request (it has to be async and support file upload)

    Thanks.