C # HttpClient PUT

For some reason, my code below that worked before, therefore, throws an exception:

public static async Task<string> HttpPut(string inUrl, string inFilePath) { using (var handler = new HttpClientHandler { AllowAutoRedirect = false }) { using (var client = new HttpClient(handler)) { //var content = new StreamContent(new FileStream(inFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true)); using (var content = new StreamContent(new FileStream(inFilePath, FileMode.Open))) { content.Headers.Remove("Content-Type"); content.Headers.Add("Content-Type", "application/octet-stream"); using (var req = new HttpRequestMessage(HttpMethod.Put, inUrl)) { string authInfo = String.Format("{0}:{1}", Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").UserName, Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").Password); authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo)); req.Headers.Add("Authorization", "Basic " + authInfo); req.Headers.Remove("Expect"); req.Headers.Add("Expect", ""); //req.Headers.TransferEncodingChunked = true; req.Content = content; // Ignore Certificate validation failures (aka untrusted certificate + certificate chains) ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true); using (HttpResponseMessage resp = await client.SendAsync(req)) { //This part is specific to the setup on an Expo we're at... if (resp.StatusCode == HttpStatusCode.Redirect || resp.StatusCode == HttpStatusCode.TemporaryRedirect) { string redirectUrl = resp.Headers.Location.ToString(); if (redirectUrl.Contains("vme-store")) { redirectUrl = redirectUrl.Replace("vme-store", "10.230.0.11"); } return await HttpPut(redirectUrl, inFilePath); } resp.EnsureSuccessStatusCode(); return await resp.Content.ReadAsStringAsync(); } } } } } } 

The exception that I get is:

 System.NotSupportedException was unhandled HResult=-2146233067 Message=The stream does not support concurrent IO read or write operations. Source=System StackTrace: at System.Net.ConnectStream.InternalWrite(Boolean async, Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) at System.Net.ConnectStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) at System.Net.Http.StreamToStreamCopy.BufferReadCallback(IAsyncResult ar) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at VizWolfInnerServer.Tools.HttpConnector.<HttpPut>d__39.MoveNext() in c:\Users\christer\Documents\Visual Studio 2012\Projects\VizWolfNew\VizWolfInnerServer\Tools\HttpConnector.cs:line 202 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at VizWolfInnerServer.Tools.VizAPIConnector.<VmeUploadMedia>d__0.MoveNext() in c:\Users\christer\Documents\Visual Studio 2012\Projects\VizWolfNew\VizWolfInnerServer\Tools\VizAPIConnector.cs:line 187 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__1(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() at System.Threading.ThreadPoolWorkQueue.Dispatch() InnerException: 

It is very difficult for me to find the correct documentation and examples for HttpClient, and I am struggling to understand why this suddenly does not work (an absolutely similar method with StringContent instead of StreamContent works fine) ...

Initially, it is called from its own thread, and then like this:

 public static async void VmeUploadMedia(string inUploadLink, string inFilePath) { string result = await HttpConnector.HttpPut(inUploadLink, inFilePath); } 

Has anyone noticed something obvious?

thanks

UPDATE

It turns out that exhibitors would display their repository name with an IP address, so I could go back to the source code, this is the best solution. The problem I encountered is related to AllowAutoRedirect = false. An exception occurred in the HttpResponseMessage resp = wait client.SendAsync (req), even if the redirect does not occur. I kind of lost why this happens, but using this code everything works now:

 public static async Task<string> HttpPut(string inUrl, string inFilePath) { using (var client = new HttpClient()) { using (var content = new StreamContent(File.OpenRead(inFilePath))) { content.Headers.Remove("Content-Type"); content.Headers.Add("Content-Type", "application/octet-stream"); using (var req = new HttpRequestMessage(HttpMethod.Put, inUrl)) { string authInfo = String.Format("{0}:{1}", Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").UserName, Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").Password); authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo)); req.Headers.Add("Authorization", "Basic " + authInfo); req.Headers.Remove("Expect"); req.Headers.Add("Expect", ""); req.Content = content; // Ignore Certificate validation failures (aka untrusted certificate + certificate chains) ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true); using (HttpResponseMessage resp = await client.SendAsync(req)) { resp.EnsureSuccessStatusCode(); return await resp.Content.ReadAsStringAsync(); } } } } } 

Thanks to the people who tried to help

+8
source share
3 answers

It turns out that exhibitors would display their repository name with an IP address, so I could go back to the source code, this is the best solution. The problem I encountered is related to AllowAutoRedirect = false. An exception occurred in the HttpResponseMessage resp = wait client.SendAsync (req), even if the redirect does not occur. I kind of lost why this happens, but using this code everything works now:

 public static async Task<string> HttpPut(string inUrl, string inFilePath) { using (var client = new HttpClient()) { using (var content = new StreamContent(File.OpenRead(inFilePath))) { content.Headers.Remove("Content-Type"); content.Headers.Add("Content-Type", "application/octet-stream"); using (var req = new HttpRequestMessage(HttpMethod.Put, inUrl)) { string authInfo = String.Format("{0}:{1}", Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").UserName, Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").Password); authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo)); req.Headers.Add("Authorization", "Basic " + authInfo); req.Headers.Remove("Expect"); req.Headers.Add("Expect", ""); req.Content = content; // Ignore Certificate validation failures (aka untrusted certificate + certificate chains) ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true); using (HttpResponseMessage resp = await client.SendAsync(req)) { resp.EnsureSuccessStatusCode(); return await resp.Content.ReadAsStringAsync(); } } } } } 

Thanks to the people who tried to help

+4
source

It sounds like you are calling HttpPut() again, but you still have a FileStream . Try to get rid of FileStream before you recursively call HttpPut() from itself.

 //This part is specific to the setup on an Expo we're at... if (resp.StatusCode == HttpStatusCode.Redirect || resp.StatusCode == HttpStatusCode.TemporaryRedirect) { string redirectUrl = resp.Headers.Location.ToString(); if (redirectUrl.Contains("vme-store")) { redirectUrl = redirectUrl.Replace("vme-store", "10.230.0.11"); } content.Dispose(); return await HttpPut(redirectUrl, inFilePath); } 

Also, you probably want to get rid of any other IDisposable objects, such as an HTTP response, to make sure all resources are freed before you go deeper into the stack trace. This is one of the problems with recursion, because when using Using statements you do not leave your scope so that they do not do their work.

0
source
 using (HttpResponseMessage resp = await client.SendAsync(req)) 

It seems that this line will create a new context for this execution, therefore, a new thread context, you might not be able to do this because you are sharing the FileStream lock.

0
source

All Articles