Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async POST request in C# .NET

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.

like image 338
MagiKruiser Avatar asked Mar 29 '13 15:03

MagiKruiser


1 Answers

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.

like image 173
MagiKruiser Avatar answered Oct 31 '22 00:10

MagiKruiser