Jer*_*vel 21 .net c# async-await windows-runtime dotnet-httpclient
我正在使用Windows运行时组件进行API调用.直到今天早些时候,我使用了HttpClient相关的模型,System.Net但转而Windows.Web使用WinRT流.
除了将using报表,交换HttpContent到IHttpContent并使用WindowsRuntimeExtensions改变我IInputStream来Stream为JSON.NET,我没有做什么特别的事情.然而,在我的16次测试中突然有3次失败,而之前一切都运转了
所有3个(集成)测试都验证我在使用无效凭据登录时收到错误响应.还有其他测试包括登录(但使用有效的凭据),它们工作得很好.给定的错误消息属于类型AggregateException并具有消息
System.AggregateException:发生一个或多个错误.--->System.Exception:找不到元素.无法显示对话框,因为尚未设置父窗口句柄.
该异常包含HRESULT值.outerexception具有-2146233088与对应0x80131500的innerexception -2147023728对应的值0x80070490.这些都不是MSDN页面上的已知错误代码.
经过调查:
堆栈跟踪:
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
Run Code Online (Sandbox Code Playgroud)
最初我的问题措辞有所不同,因为实际问题似乎是隐藏的.我发现GET请求HttpClient返回给调用者而不是等待调用的结果(并执行方法的其余部分).
在我的项目中,执行该行将var data = await myHttpClient.GetAsync(url);返回带有非构造对象的调用方法,并且在GetAsync()调用之后的后续行不会被执行.
添加.ConfigureAwait(false)以阻止它返回没有任何区别.
在AggregateException当用户试图用无效凭证登录异常.由于某种原因,HttpClient决定抛出一个异常然后没有给我一个我可以使用的返回值.这里的问题是,它并没有告诉我什么样的异常:捕捉COMException,TaskCanceledException,AggregateException并Exception只会触发了后者.
我还发现异步集成测试不适用于多线程MSTest环境,因此我解释了其他几个失败的测试(但是单独工作得很好)
最后,我还有一个演示问题的示例(但我无法提供基本身份验证的Web服务)!
[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;
}
}
Run Code Online (Sandbox Code Playgroud)
使用有效密码执行此代码将返回,true而无效密码将抛出AggregateException.
现在我正在通过Exception围绕调用捕获一个将军来解决这个问题,GetAsync()但这是非常简陋的,我想知道为什么这个不完整的异常首先被抛出.
Yuv*_*kov 30
重建你的例子并玩弄后,我想出了会发生什么.
var data = await client.GetAsync(new Uri("https://mytestdomain/v2/apikey?format=Json"));
Run Code Online (Sandbox Code Playgroud)
该GetAsync方法使用无效凭据调用HTTP请求.发生的情况是返回的请求尝试查找一个窗口,您可以在其中输入正确的凭据,但找不到.因此它会抛出一段Element Not Found时间来搜索那个窗口.
这可以通过创建一个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;
}
Run Code Online (Sandbox Code Playgroud)

| 归档时间: |
|
| 查看次数: |
13277 次 |
| 最近记录: |