0
votes

Very strange problem (all code is in PCL).

When I call await client.PostAsync() against a webservice (API's), I get the TaskCanceledException.

Few things to note:

This is running fine on Android devices. It only happens when I run the app on iOS, but...

... to make it even stranger, I can make it run on iOS if I use different (physical) server that hosts the API's that I query with await client.PostAsync().

So,

To make it even more strange, both servers run exactly the same webservice, there is 0 difference, the only difference is the servers are on different sites with different client. So the fault is not with the queried webservice throwing timing out or cancelling the request.

Both servers have valid (trusted) SSL certificate so it's not an SSL related issue.

I am stuck. I have already tried ModernHttpClient and increaing the client.TimeSpan.

I also checked the ex.CancellationToken.IsCancellationRequested, which is false, so it's pretty safe to assume it was some time of "timeout". However, when I run the Post request from PostMan manually against that API, it's clear the webservice works fine (there is no timeout).

public class TokenService
{
    private HttpClient client;
    private App app;

    public TokenService()
    {
        //client = new HttpClient();

        client = new HttpClient(new NativeMessageHandler());
        client.Timeout = TimeSpan.FromMinutes(30);

        client.MaxResponseContentBufferSize = 256000;
        app = (App)Application.Current;
    }

    public class TokenResponse
    {
        public String access_token;
        public Int32 expires_in;
    }

    public async Task<String> GetNewToken()
    {
        // check if valid token already stored and within expiry DateTime

        if(Token.BearerToken != null)
        {
            if (Token.expiry > DateTime.Now)
                return Token.BearerToken;
        }

        var tokenUlr = app.WebServicesHostName + "/token";

        var tokenResponse = new TokenResponse();

        try
        {
            var content = new FormUrlEncodedContent(new[]
            {
                // this needs to be stored somewhere safe:
                new KeyValuePair<string, string>("username", "validusernamehere"),
                new KeyValuePair<string, string>("password", "validpasshere")
            });

            var response = await client.PostAsync(tokenUlr, content); // <<***EXCEPTION HERE

            if (response.StatusCode == HttpStatusCode.OK)
            {
                var token = await response.Content.ReadAsStringAsync();

                tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(token);

                Token.BearerToken = tokenResponse.access_token;
                Token.expiry = DateTime.Now.AddSeconds(tokenResponse.expires_in - 30);

                return tokenResponse.access_token;
            }
            else
            {
                return null;

            }
        }
        catch(TaskCanceledException ex)
        {
            String message = ex.Message;
            String source = ex.Source;
            CancellationToken token = ex.CancellationToken;



            return null;
        }
        catch(Exception ex)
        {
            String test = ex.Message;
            return null;
        }
    }
}

Exception details:

{System.Threading.Tasks.TaskCanceledException: A task was canceled.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0002d] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:179 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:357 at System.Net.Http.HttpClientHandler+c__async0.MoveNext () [0x004c1] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs:391

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00027] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:176 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:535 at System.Net.Http.HttpClient+c__async0.MoveNext () [0x000a9] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs:276

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00027] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:176 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.128/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:357 at XamarinMO.Services.TokenService+d__4.MoveNext () [0x000e3] in C:\Users\johns\OneDrive\Sources\WinMan API and Xamain App\XamarinMO\XamarinMO\XamarinMO\Services\TokenService.cs:67 }

1
Could you post a sample of code ?OrcusZ
@OrcusZ sure, I amended the post.John S
it's very strange. because yoru code seems to be correct. Can you add a finaly in yourtry catch and dispose HttpClient. Futhermore, do you run this code into a thread or not ?OrcusZ
Are you able to recreate the problem in a minimal example: New Project, add just the call to your service and see if it works?Kai Brummund
Use Fiddler to check that the query is returning successfully on iOS.David Oliver

1 Answers

2
votes

After many MANY hours, I found the solution:

It can be fixed by changing the TLS setting under project properties to Mono instead of Apple. This is due to a bug in the new Apple TLS default setting for SSL/TLS on iOS.