发生了一个或多个错误:PostAsJsonAsync

pet*_*ski 8 c# json

这是我得到的错误:

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
Run Code Online (Sandbox Code Playgroud)

这是方法:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我调用了很多这样的方法,除了这个之外它们都有效.当它被击中时,需要花费很多时间,然后抛出这个异常.使用所有其他方法时,错误不会发生.

这是内在的例外:

Inner.System.Threading.Tasks.TaskCanceledException: A task was canceled.
Run Code Online (Sandbox Code Playgroud)

这是我的GetCLient()方法:

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

    return new HttpClient(handler)
    {
        BaseAddress = uri
    };
}
Run Code Online (Sandbox Code Playgroud)

这是API方法:

[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();
    }
Run Code Online (Sandbox Code Playgroud)

可能发生超时.

Fiddler返回此错误:等待操作超时.

sco*_*732 13

.Result尝试将Task变为T.它同步阻止等待任务完成,并且只有在没有异常发生时才返回T. 您应该预期的两种类型的异常是OperationCanceledExceptions/TaskCanceledExceptions(当HTTP请求超时或使用CancellationToken且令牌被取消时 - 我不认为后者适用于此处)和一般/ HTTP相关的异常.

您可能正在遇到HTTP超时方案.是否需要很长时间才能抛出异常?如果没有,你的GetHttpClient方法是什么样的?是明确设置超时还是取消令牌?

如果你想坚持使用同步方法而不返回任务,你应该做这样的事情:

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.
}
Run Code Online (Sandbox Code Playgroud)

如果你愿意接受异步暴跌,那么这就是你想要的更多:

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有关.Result调用如何使用HttpClient的更多信息,请参阅此处:在等待任务结果时会发生什么?