Search code examples
c#.netgarbage-collection

VSTO Outlook Plugin - HttpClient.PostAsync fails without fiddler


I unfortunately had Fiddler running for the whole time I was developing this feature in the plugin and since deploying to clients I found that it will not work for anyone - unless they run fiddler as well! It also does not work on my development machine if I stop running Fiddler.

The main error is Error while copying content to a stream.. So I investigated the possibility of the data I'm POSTing being released by the GC before it finished hitting the server (That, to me, explained why running Fiddler solved it - as I believe the request gets sent to Fiddler first, and then Fiddler sends it to the server). However I couldn't find anything to support that this might be the problem. I have tried making sure it holds onto the data but I don't feel like I'm going down the right route.

The code is roughly like this:

HttpClientHandler httpHandler = new HttpClientHandler { UseDefaultCredentials = true };
var client = new HttpClient(httpHandler, false);
client.BaseAddress = new Uri(BaseUrl + "api/job/PostTest");

var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantCulture));

content.Add(new StringContent(mailItem.HTMLBody, Encoding.UTF8), "BodyHtml");
// content.Add()'s... Omitted for brevity

var response = client.PostAsync(BaseUrl + "api/job/PostTest", content);

response.ContinueWith(prevTask => {

    if (prevTask.Result.IsSuccessStatusCode)
    {
        System.Diagnostics.Debug.WriteLine("Was success");
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("Was Error");
    }

}, System.Threading.Tasks.TaskContinuationOptions.OnlyOnRanToCompletion);



response.ContinueWith(prevTask =>{
    MessageBox.Show(prevTask.Exception.ToString());
}, System.Threading.Tasks.TaskContinuationOptions.OnlyOnFaulted);

The full exception details are:

   System.AggregateException: One or more errors occurred. ---> System.Net.Http.HttpRequestException: Error while copying content to a stream. ---> System.IO.IOException: The read operation failed, see inner exception. ---> System.Net.WebException: The request was aborted: The request was canceled.
   at System.Net.ConnectStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state)
   at System.Net.Http.StreamToStreamCopy.StartRead()
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---
---> (Inner Exception #0) System.Net.Http.HttpRequestException: Error while copying content to a stream. ---> System.IO.IOException: The read operation failed, see inner exception. ---> System.Net.WebException: The request was aborted: The request was canceled.
   at System.Net.ConnectStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state)
   at System.Net.Http.StreamToStreamCopy.StartRead()
   --- End of inner exception stack trace ---<---

If anyone could point me to some resources that help me or point out where I'm going wrong that would help a lot!


Solution

  • After much searching and much messing about I've not been able to solve this problem using HttpClient so instead what I've done is using WebClient. In case someone else has this problem in the future I'm posting what I ended up using:

    System.Net.WebClient wc = new System.Net.WebClient();
    wc.Headers.Add("Content-Type", String.Format("multipart/form-data; boundary=\"{0}\"", multipartFormBoundary));
    wc.UseDefaultCredentials = true;
    
    try
    {
        var wcResponse = wc.UploadData(BaseUrl + "api/job/PostJobEmailNote", byteArray);
    }
    catch(Exception e)
    {
        // response status code was not in 200's 
    }