HttpClient PostAsync()无效

时间:2016-12-22 12:10:54

标签: c# xamarin xamarin.forms httpclient

在我的Xamarin Forms App中

我正在尝试将一个Json字符串发布到我的Web服务,它是RestFul API 当我使用以下代码时:

public static async Task<bool> SaveRolAsync(Methods Method, Role Rol)
    {
        try
        {
            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            var uri = ("http://myservice.com/roles/");
            HttpResponseMessage response = null;

            try
            {
                var jSettings = new JsonSerializerSettings();
                jSettings.NullValueHandling = NullValueHandling.Ignore;
                jSettings.MissingMemberHandling = MissingMemberHandling.Ignore;

                var JsonData = JsonConvert.SerializeObject(Rol);
                var RoleContent = new StringContent(JsonData, Encoding.UTF8, "application/json");

                if (Method == Methods.PUT || Method == Methods.PATCH)
                {
                    response = await client.PutAsync(uri, RoleContent);
                }

                if (Method == Methods.POST)
                {
                    response = await client.PostAsync(uri, RoleContent);
                }

                if (Method == Methods.DELETE)
                {
                    throw new NotImplementedException();
                }

                return response.IsSuccessStatusCode;

            }
            catch (JsonException jse)
            {
                return false;
            }
        }
        catch (Exception ex)
        {
            // Exceptions Throws here
            // @T This line i got The request requires buffering data to succeed
            return false;
        }
    }

Exception抛出:

  

请求需要缓冲数据才能成功

堆栈追踪:

  

{System.Net.WebException:请求需要缓冲数据   成功。在System.Net.HttpWebRequest.EndGetResponse   (System.IAsyncResult asyncResult)[0x00064] in   :0点   System.Threading.Tasks.TaskFactory 1[TResult].FromAsyncCoreLogic (System.IAsyncResult iar, System.Func 2 [T,TResult] endFunction,   System.Action 1[T] endAction, System.Threading.Tasks.Task 1 [TResult]   promise,System.Boolean requiresSynchronization)[0x00014] in   :0   ---从抛出异常的先前位置开始的堆栈跟踪结束--- at   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()   [0x0000c] in:0 at   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess   (System.Threading.Tasks.Task任务)[0x0004e] in   :0点   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification   (System.Threading.Tasks.Task任务)[0x0002e] in   :0点   System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd   (System.Threading.Tasks.Task任务)[0x0000b] in   :0点   System.Runtime.CompilerServices.ConfiguredTaskAwaitable 1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in <a66f207c1e5949e9a252c01e27bbd34e>:0 at System.Net.Http.HttpClientHandler+<SendAsync>c__async0.MoveNext () [0x0041e] in <566d6cf6576345098cb5e08ad43d5e78>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <a66f207c1e5949e9a252c01e27bbd34e>:0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0004e] in <a66f207c1e5949e9a252c01e27bbd34e>:0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in <a66f207c1e5949e9a252c01e27bbd34e>:0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in <a66f207c1e5949e9a252c01e27bbd34e>:0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable 1 + ConfiguredTaskAwaiter [TResult] .GetResult   ()[0x00000] in:0 at   System.Net.Http.HttpClient + c__async0.MoveNext()   &lt; 566d6cf6576345098cb5e08ad43d5e78&gt;中的[0x000f3]:0   ---从抛出异常的先前位置开始的堆栈跟踪结束--- at   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()   [0x0000c] in:0 at   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess   (System.Threading.Tasks.Task任务)[0x0004e] in   :0点   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification   (System.Threading.Tasks.Task任务)[0x0002e] in   :0点   System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd   (System.Threading.Tasks.Task任务)[0x0000b] in   :0点   System.Runtime.CompilerServices.TaskAwaiter`1 [TResult] .GetResult()   [0x00000] in:0 at   MyAPP.Webservice + d__4.MoveNext()[0x000d0] in   C:\ MyProject \ Classes \ Webservice.cs:140}

**同时尝试:SendAsync()TyM.Wiśnicki**

public static async Task<bool> SaveRolAsync(MediwareLib.Methods Method, Role Rol)
    {
        try
        {
            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            var uri = (BaseRequestUrl + "roles/");
            HttpResponseMessage response = null;
            var request = new HttpRequestMessage();

            try
            {
                var jSettings = new JsonSerializerSettings();
                jSettings.NullValueHandling = NullValueHandling.Ignore;
                jSettings.MissingMemberHandling = MissingMemberHandling.Ignore;

                var JsonData = JsonConvert.SerializeObject(Rol);

                var RoleContent = new StringContent(JsonData, Encoding.UTF8, "application/json");

                if (Method == MediwareLib.Methods.PUT || Method == MediwareLib.Methods.PATCH)
                {
                    request = new HttpRequestMessage(HttpMethod.Put, uri);
                    request.Content = RoleContent;

                    response = await client.SendAsync(request,
                    HttpCompletionOption.ResponseHeadersRead);
                }

                if (Method == MediwareLib.Methods.POST)
                {
                    request = new HttpRequestMessage(HttpMethod.Post, uri);
                    request.Content = RoleContent;

                    response = await client.SendAsync(request,
                    HttpCompletionOption.ResponseHeadersRead);
                }

                if (Method == MediwareLib.Methods.DELETE)
                {
                    throw new NotImplementedException();
                    // response = await client.DeleteAsync(uri + Rol.Id);
                }

                return response.IsSuccessStatusCode;

            }
            catch (JsonException jse)
            {
                Globals.Log("SaveRolAsync: " + jse.ToString());
                return false;
            }
        }
        catch (Exception ex)
        {
            Globals.Log("SaveRolAsync: " + ex.ToString());
            return false;
        }

    }

enter image description here

2 个答案:

答案 0 :(得分:1)

您可以SendAsync()使用HttpCompletionOption.ResponseHeadersRead代替PostAsync(),问题在于阅读回复,在未准备就绪时进行阅读。

var request = new HttpMessageRequest(yourUrl);
request.Content = yourContent;
var response = await client.SendAsync(request, 
HttpCompletionOption.ResponseHeadersRead);

使用HttpCompletionOption.ResponseHeadersRead

  

一旦响应可用并且读取标题,操作就应该完成。内容尚未阅读。

修改 您可以使用HttpWebRequest代替HttpClient

   public async Task<string> PostTest(object sampleData, string uri)
    {
        var request = (HttpWebRequest) WebRequest.Create(new Uri(uri));
        request.ContentType = "application/json";
        request.Method = "POST";
        request.Timeout = 4000; //ms
        var itemToSend = JsonConvert.SerializeObject(sampleData);
        using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
        {
            streamWriter.Write(itemToSend);
            streamWriter.Flush();
            streamWriter.Dispose();
        }

        // Send the request to the server and wait for the response:  
        using (var response = await request.GetResponseAsync())
        {
            // Get a stream representation of the HTTP web response:  
            using (var stream = response.GetResponseStream())
            {
                var reader = new StreamReader(stream);
                var message = reader.ReadToEnd();
                return message;
            }
        }
    }

答案 1 :(得分:1)

由于您使用的是.Result.Waitawait,因此最终会导致代码中出现死锁

您可以在ConfigureAwait(false)方法中使用async 防止死锁

像这样:

response = await client.PostAsync(uri, RoleContent).ConfigureAwait(false);
  

您可以尽可能使用ConfigureAwait(false)“禁止阻止异步代码”。