Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One or more errors occurred: PostAsJsonAsync

Tags:

json

c#

This is the error I get:

One or more errors occurred.
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at myProject.mymethod(Int32[] myIds) in path\MyClass.cs:line 758

And here's that method:

private void mymethod(int[] myIds)
{
    var uri = new Uri(string.Format(UriPath, string.Format(MyPath)));
    var client = GetHttpClient(uri);

    var postModel = new PostModel
    {
        Ids = myIds,
        LastUpdate = NewItem ? null : _lastUpdated
    };

    if (client != null)
    {
        var response = client.PostAsJsonAsync(uri, postModel).Result;//this line crashes

        if (response.IsSuccessStatusCode)
        {
            //doSomething
        }
    }
}

I call a lot of methods like this and all of them work except this one. When it's hit, it takes a lot of time and then this exception is throws. With all of the other methods the error doesn't happen.

This is the inner exception:

Inner.System.Threading.Tasks.TaskCanceledException: A task was canceled.

Here's my GetCLient() method:

private HttpClient GetHttpClient(Uri uri)
{
    var handler = new HttpClientHandler
    {
        CookieContainer = CoockieContainer
    };

    return new HttpClient(handler)
    {
        BaseAddress = uri
    };
}

Here's the API method:

[HttpPost]
    public IList<MyModel> MyAPIMethod(PostModel model)
    {
        List<MyModel> myTranslations;
        using (var db = new myEntities(GetDbConnStrByUser(new GetCookies().GetUserName())))
        {
            myTranslations = db.tblTranslations.Where(it => model.Ids.Contains(it.id)
                                    && (!model.Update.HasValue || it.update > model.LastUpdate.Value))
                                    .Select(it => new MyModel
                                    {
                                        Id = it.id,
                                        Name = it.name,
                                        Description = it.desc,
                                        LanguageId = it.language_id                                            
                                    }).ToList();
        }

        return myTranslations.GroupBy(x => new { x.Id, x.LanguageId }).Select(x => x.First()).ToList();
    }

Maybe a timeout occurs.

Fiddler returns this error: The wait operation timed out.

like image 358
petko_stankoski Avatar asked Oct 13 '14 15:10

petko_stankoski


1 Answers

.Result tries to turn Task into T. It synchronously blocks waiting for the task to complete and will only return T if no exceptions occur. The two types of exceptions you should anticipate are OperationCanceledExceptions/TaskCanceledExceptions (when the HTTP request times out or a CancellationToken was used and the token was cancelled--I don't think the latter is applicable here) and general/HTTP-related exceptions.

You're probably running into the HTTP timeout scenario. Is it taking a long time for the exception to get thrown? If not, what does your GetHttpClient method look like? Is it explicitly setting timeouts or cancellation tokens?

If you want to stick with the synchronous approach and not returns Tasks, you should do something like this instead:

try
{    
    var response = client.PostAsJsonAsync(uri, postModel).Result;//this line crashes
} 
catch (OperationCanceledException oce) 
{
    // Tell the user that the request timed our or you cancelled a CancellationToken
}
catch (Exception exc) 
{
    // Look at the HttpClient docs and try to catch something more specific.  You don't want
    // to swallow StackOverflowExceptions or OutOfMemoryExceptions.
}

If you're willing to take the async plunge, this is more what you're looking for:

private async Task mymethodAsync(int[] myIds)
{
    var uri = new Uri(string.Format(UriPath, string.Format(MyPath)));
    var client = GetHttpClient(uri);

    var postModel = new PostModel { ... };

    if (client != null)
    {
        try 
        {
            var response = await client.PostAsJsonAsync(uri, postModel);

            if (response.IsSuccessStatusCode)
            {
                //doSomething
            }
        }
        catch (OperationCanceledException oce) 
        {
            // because timeouts are still possible
        }
        catch (Exception exc) {
            // Because other things can still go wrong too (HTTP 500, parsing errors)
        }
    }
}

See here for more info on how .Result call works w/HttpClient: What happens while waiting on a Task's Result?

like image 175
scottt732 Avatar answered Sep 24 '22 15:09

scottt732