Я работаю над компонентом Runtime Windows, который вызывает вызовы API. До сегодняшнего дня я использовал HttpClient
и связанные с ним модели от System.Net
, но вместо этого переключился на Windows.Web
, чтобы использовать потоки WinRT.
Помимо изменения операторов using
, заменяя HttpContent
на IHttpContent
и используя WindowsRuntimeExtensions
, чтобы изменить мой IInputStream
на Stream
для JSON.NET, мне не нужно было ничего делать, Однако неожиданно 3 из моих 16 тестов терпят неудачу, тогда как раньше все работало.
Все тесты (интеграция) подтверждают, что я получаю сообщение об ошибке при входе в систему с недопустимыми учетными данными. Существуют и другие тесты, включающие вход в систему (но с действительными учетными данными), и они работают нормально. Данное сообщение об ошибке имеет тип AggregateException
и имеет в качестве сообщения
System.AggregateException
: Произошла одна или несколько ошибок. --- >System.Exception
: Элемент не найден.Диалоговое окно невозможно отобразить, поскольку дескриптор родительского окна не установлен.
Исключение содержит значения HRESULT. Outerexception имеет значение -2146233088
, которое соответствует 0x80131500
, в то время как innerexception имеет -2147023728
, что соответствует 0x80070490
. Ни один из них не является известным кодом ошибки на странице MSDN.
Следующее исследование:
-
0x80131500
соответствуетCOR_E_EXCEPTION
-
0x80070490
соответствуетERROR_NOT_FOUND
StackTrace:
Result StackTrace:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at xx.Models.Requests.GetRequest.<ExecuteRequestAsync>d__0.MoveNext() in c:\Users\jeroen\Github\Windows-app\xx\xx\Models\Requests\Request.cs:line 17
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at xx.ApiDispatcher.<ExecuteAsync>d__0`2.MoveNext() in c:\Users\jeroen\Github\Windows-app\xx\xx\ApiDispatcher.cs:line 40
--- End of inner exception stack trace ---
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 xx.ApiDispatcher.Execute[TCallResult,TResponseObject](ApiCall`2 call) in c:\Users\jeroen\Github\Windows-app\xx\xx\ApiDispatcher.cs:line 22
Первоначально мой вопрос был сформулирован несколько иначе, потому что фактическая проблема казалась скрытой. Я узнал, что запрос GET с помощью HttpClient
возвращается обратно вызывающему, а не ожидает результата вызова (и выполняет оставшуюся часть метода).
В моем проекте выполнение строки var data = await myHttpClient.GetAsync(url);
вернется к вызывающему методу с непостроенным объектом, а последующие строки, которые появляются после вызова GetAsync()
, просто не выполняются.
Добавление .ConfigureAwait(false)
, чтобы остановить его от возврата, не помогло.
AggregateException
вызывается, когда пользователь пытается войти в систему с недопустимыми учетными данными. По какой-то причине HttpClient
решает выбросить исключение, не указывая мне возвращаемое значение, которое я мог бы использовать. Проблема здесь в том, что она не говорит мне, какое исключение: catching COMException
, TaskCanceledException
, AggregateException
и Exception
вызывает только последний.
Я также выяснил, что тесты асинхронной интеграции не очень хорошо работают с многопоточной средой MSTest, поэтому объясняются несколько других неудачных тестов, которые у меня были (но работали просто отлично)
Я также, наконец, приведу пример, демонстрирующий проблему (но я не могу предоставить веб-сервис, который принимает базовый auth)!
[TestMethod]
public void TestMethod3()
{
Assert.IsTrue(new Test().Do().AsTask().Result);
}
public sealed class Test
{
public IAsyncOperation<bool> Do()
{
return DoSomething().AsAsyncOperation();
}
private async Task<bool> DoSomething()
{
var client = new HttpClient();
var info = "[email protected]:nopass";
var token = Convert.ToBase64String(Encoding.UTF8.GetBytes(info));
client.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("Basic", token);
var data = await client.GetAsync(new Uri("https://mytestdomain/v2/apikey?format=Json"));
return true;
}
}
Выполнение этого кода с допустимым паролем вернет true
, в то время как недопустимый пароль вызовет AggregateException
.
Сейчас я работаю над проблемой, перехватив общий Exception
вокруг вызова GetAsync()
, но это очень рудиментарно, и я хотел бы знать, почему это незавершенное исключение выбрасывается в первую очередь.