0

My C# app uploads file to some API, I'm using multipart request, i.e I'm uploading a json string and binary contect of the file, it works fine for most files, but for very few it does nothing, I mean let's try for file named file.pdf:

My code looks roughly as follows:

public async Task<Dictionary<string , string>> Upload(string filePath)
{   
      FileInfo fi = new FileInfo(FilePath);

      string jsonString="some json string";

      byte[] fileContents=File.ReadAllBytes(fi.FullName);

      Uri webService = new Uri(url);

      HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post , webService);

      requestMessage.Method = HttpMethod.Post;

      requestMessage.Headers.Add("Authorization" , "MyKey1234");

      const string boundry = "------------------My-Boundary";

      MultipartFormDataContent multiPartContent = new MultipartFormDataContent(boundry);

      ByteArrayContent byteArrayContent = new ByteArrayContent(fileContents);

      multiPartContent.Add(byteArrayContent);

      requestMessage.Content = multiPartContent;

      HttpClient httpClient = new HttpClient();

      Console.WriteLine("before");

HttpResponseMessage httpResponse = await httpClient.SendAsync(requestMessage , HttpCompletionOption.ResponseContentRead , CancellationToken.None);

Console.WriteLine("after");
    }

The caller:

myDictionary = await Upload(filePath);

Output:

before
Press any key to continue . . .

I mean there is no exception, nothing, what is this? a bug?

Edit

The structure of the console app is as follows:

class Program
{
    static void Main(string[] args)
    {
        new MyClass().Start();
    }
}

And inside MyClass:

public async void Start()
{
  myDictionary = await Upload(filePath);
}
Kzryzstof
  • 7,688
  • 10
  • 61
  • 108
exe
  • 181
  • 1
  • 1
  • 10
  • 2
    where is the caller here ? we need the full class in order to give you an explanation – BRAHIM Kamel Jul 29 '18 at 12:41
  • Can you add `httpResponse.EnsureSuccessStatusCode()` line and break or add watch to that to see the response of the API? – Boxed Jul 29 '18 at 12:55
  • @Boxed I tried it now, but it still prints only `"before"` string – exe Jul 29 '18 at 12:56
  • 2
    @exe Please edit your question to include a full [MCVE](https://stackoverflow.com/help/mcve). – Progman Jul 29 '18 at 13:02
  • @exe what I meant was put a breakline at the response code, see the contents of the reponse and check the status code that was received. – Boxed Jul 29 '18 at 13:03
  • 3
    It is highly likely that the Main method of your console application does not have the async keyword in its declaration and, as such, will not wait for the response. Could you post the main method code? – Kzryzstof Jul 29 '18 at 13:07
  • @exe There you go :) – Kzryzstof Jul 29 '18 at 13:19
  • @Kzrystof I add the current structure, can you take a look if you see something missing? – exe Jul 29 '18 at 13:22
  • You are not running your code in an async context, please read https://stackoverflow.com/questions/5095183/how-would-i-run-an-async-taskt-method-synchronously – Progman Jul 29 '18 at 13:25
  • @exe I have added the information in an answer. – Kzryzstof Jul 29 '18 at 13:29

1 Answers1

3

As explained in the comment section, your main method does not await the awaitable call and will not wait for the HttpClient instance to process the response.

If the console app is for testing purposes, you can call the .Result property on the task instance returned by the method, like this:

new MyClass().Start().Result;

However, it would be best to use the async keyword on the main method that has been made available in C# 7.1, like this:

class Program
{
   static async Task Main(string[] args)
   {
        await new MyClass().Start();
   }
}

Finally, as recommended, you should add the suffix 'Async' to your async method names. For instance, Start would be named StartAsync.

Kzryzstof
  • 7,688
  • 10
  • 61
  • 108