c# – Windows.Web.Http.HttpClient#当无效凭据与基本身份验证一起使用时,GetAsync会引发不完整的异常

我正在使用一个Windows运行时组件来进行API调用。直到今天早些时候,我使用了来自System.Net的HttpClient和相关模型,但是切换到Windows.Web来利用WinRT流。

除了更改使用语句,将HttpContent交换到IHttpContent并使用WindowsRuntimeExtensions将我的IInputStream更改为Stream for JSON.NET,我没有必要做任何特别的事情。然而突然之间,我16次测试中的3次失败,而以前的一切都奏效。

所有3(集成)测试验证当使用无效凭据登录时收到错误响应。还有其他测试,包括登录(但有效的凭据),他们工作正常。给定的错误消息的类型为AggregateException并具有消息

System.AggregateException: One or more errors occurred. —> System.Exception: Element not found.

A dialog cannot be displayed because the parent window handle has not been set.

该异常包含HRESULT值。 outerexception具有值-2146233088,对应于0x80131500,而innerexception具有对应于0x80070490的-2147023728。这些都不是the MSDN page上的已知错误代码。

经调查:

> 0x80131500 corresponds to COR_E_EXCEPTION
> 0x80070490 corresponds to ERROR_NOT_FOUND

堆栈跟踪:

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

原来我的问题的措词有些不一样,因为实际的问题似乎是隐藏的。我发现HttpClient的GET请求返回给调用者,而不是等待调用的结果(并执行该方法的其余部分)。

在我的项目中,执行行var data = await myHttpClient.GetAsync(url);将返回到具有非构造对象的调用方法,并且后来的GetAsync()调用之后的行根本不被执行。

添加.ConfigureAwait(false)来阻止它返回没有任何变化。

当用户尝试使用无效凭据登录时,会抛出AggregateException。由于某些原因,HttpClient决定抛出一个异常,而不给我一个可以使用的返回值。这里的问题是它没有告诉我什么样的异常:捕捉COMException,TaskCanceledException,AggregateException和Exception仅触发后者。

我还发现,异步集成测试在多线程MSTest环境中不能很好地工作,因此我解释了其他几个失败的测试(但是单独工作得很好)

最后我也有一个例子来证明这个问题(但是我不能提供一个基本认证的webservice)!

[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 = "jeroen.vannevel@something.com: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。

现在我正在解决这个问题,通过在GetAsync()的调用中捕获一般的异常,但这是非常初步的,我想知道为什么这个不完整的异常被抛在第一位。

在重建你的例子和玩弄之后,我想出了会发生什么。

var data = await client.GetAsync(new Uri("https://mytestdomain/v2/apikey?format=Json"));

GetAsync方法调用具有无效凭据的HTTP请求。发生什么是返回的请求尝试查找一个窗口,您可以在其中输入正确的凭据,但找不到一个。因此,它在搜索该窗口时会抛出一个未找到的元素。

这可以通过创建HttpBaseProtocolFilter并将AllowUI属性设置为false,然后将其传递到HttpClient来修复:

private async Task<bool> DoSomething()
{
    var httpBaseFilter = new HttpBaseProtocolFilter
    {
        AllowUI = false
    };

    var client = new HttpClient(httpBaseFilter);
    var info = "jeroen.vannevel@something.com: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;
}
http://stackoverflow.com/questions/24361588/windows-web-http-httpclientgetasync-throws-an-incomplete-exception-when-invalid

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c# – Windows.Web.Http.HttpClient#当无效凭据与基本身份验证一起使用时,GetAsync会引发不完整的异常