5
votes

In my Xamarin Forms App

I'm trying to Post a Json String to my webservice wich is RestFul API when i use the following code:

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;
        }
    }

The Exception throws:

The request requires buffering data to succeed

Stack Trace:

{System.Net.WebException: The request requires buffering data to succeed. at System.Net.HttpWebRequest.EndGetResponse (System.IAsyncResult asyncResult) [0x00064] in :0 at System.Threading.Tasks.TaskFactory1[TResult].FromAsyncCoreLogic (System.IAsyncResult iar, System.Func2[T,TResult] endFunction, System.Action1[T] endAction, System.Threading.Tasks.Task1[TResult] promise, System.Boolean requiresSynchronization) [0x00014] in :0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0004e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in :0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1+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.ConfiguredTaskAwaitable1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in :0 at System.Net.Http.HttpClient+c__async0.MoveNext () [0x000f3] in <566d6cf6576345098cb5e08ad43d5e78>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0004e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in :0 at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in :0 at MyAPP.Webservice+d__4.MoveNext () [0x000d0] in C:\MyProject\Classes\Webservice.cs:140 }

**Also Tried: SendAsync() Ty M. 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
So what did your research show? Did you read The request requires buffering data to succeed HttpClient and Head request with HttpClient? Did you notice you're sending a PUT even if (Method == Methods.POST)? Is your service responding with a redirect?CodeCaster
Ofc i did read other stackoverflow posts but i want to send a json string not a google request.Stefan van de Laarschot
An HTTP request is an HTTP request, whether it contains search results or JSON data.CodeCaster
Would be nice to know in which line the exception is thrown :)Dennis Schröer
Please attach the full stack trace.Cheesebaron

2 Answers

2
votes

You can use SendAsync() with HttpCompletionOption.ResponseHeadersRead instead PostAsync(), the problem is with reading response, it's reading when it not ready.

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

Using HttpCompletionOption.ResponseHeadersRead

The operation should complete as soon as a response is available and headers are read. The content is not read yet.

Edit You can use HttpWebRequest instead 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;
            }
        }
    }
7
votes

Since you are using .Result or .Wait or await this will end up causing a deadlock in your code.

you can use ConfigureAwait(false) in async methods for preventing deadlock

like this:

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

you can use ConfigureAwait(false) wherever possible for Don't Block Async Code .