Tuesday, 15 March 2011

c# - Windows.Web.Http.HttpClient#GetAsync throws an incomplete exception when invalid credentials are used with basic authentication -



c# - Windows.Web.Http.HttpClient#GetAsync throws an incomplete exception when invalid credentials are used with basic authentication -

i working on windows runtime component makes api calls. until before today used httpclient , related models system.net switched on windows.web instead leverage winrt streams.

aside changing using statements, swapping httpcontent ihttpcontent , using windowsruntimeextensions alter iinputstream stream json.net, didn't have special. 3 out of 16 tests fail whereas worked.

all 3 (integration) tests validate receive error response when logging in invalid credentials. there other tests include logging in (but valid credentials) , work fine. given error message of type aggregateexception , has message

system.aggregateexception: 1 or more errors occurred. ---> system.exception: element not found.

a dialog cannot displayed because parent window handle has not been set.

the exception contains hresult values. outerexception has value -2146233088 corresponds 0x80131500 while innerexception has -2147023728 corresponds 0x80070490. neither of known error code on the msdn page.

following investigation:

0x80131500 corresponds to cor_e_exception 0x80070490 corresponds to error_not_found

stacktrace:

result stacktrace: @ system.runtime.compilerservices.taskawaiter.throwfornonsuccess(task task) @ system.runtime.compilerservices.taskawaiter.handlenonsuccessanddebuggernotification(task task) @ system.runtime.compilerservices.taskawaiter`1.getresult() @ 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 previous location exception thrown --- @ system.runtime.compilerservices.taskawaiter.throwfornonsuccess(task task) @ system.runtime.compilerservices.taskawaiter.handlenonsuccessanddebuggernotification(task task) @ system.runtime.compilerservices.taskawaiter`1.getresult() @ 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 --- @ system.threading.tasks.task.throwifexceptional(boolean includetaskcanceledexceptions) @ system.threading.tasks.task`1.getresultcore(boolean waitcompletionnotification) @ system.threading.tasks.task`1.get_result() @ xx.apidispatcher.execute[tcallresult,tresponseobject](apicall`2 call) in c:\users\jeroen\github\windows-app\xx\xx\apidispatcher.cs:line 22

originally question worded differently because actual problem seemed hidden. have found out request httpclient returns caller instead of awaiting result of phone call (and executing rest of method).

in project, executing line var info = await myhttpclient.getasync(url); homecoming calling method non-constructed object , subsequent lines come after getasync() phone call not executed.

adding .configureawait(false) stop going did not create difference.

the aggregateexception thrown when user tries login invalid credentials. reason httpclient decides throw exception without giving me homecoming value use. problem here not tell me kind of exception: catching comexception, taskcanceledexception, aggregateexception , exception trigger latter.

i have found out asynchronous integration tests not work multithreaded mstest environment, explains several other failed tests had (but worked fine individually)

i also, finally, have illustration demonstrates problem (but can't provide webservice takes basic auth)!

[testmethod] public void testmethod3() { assert.istrue(new test().do().astask().result); } public sealed class test { public iasyncoperation<bool> do() { homecoming 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 info = await client.getasync(new uri("https://mytestdomain/v2/apikey?format=json")); homecoming true; } }

executing code valid password homecoming true while invalid password throw aggregateexception.

right working around problem catching general exception around phone call getasync() rudimentary , i'd know why incomplete exception thrown in first place.

after reconstructing illustration , playing around, figured out happens.

var info = await client.getasync(new uri("https://mytestdomain/v2/apikey?format=json"));

the getasync method invokes http request invalid credentials. happens returned request tries window can come in right credentials, doesn't find one. hence throws element not found while searching window.

this can fixed creating httpbaseprotocolfilter , setting allowui property false , passing 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 info = await client.getasync(new uri("https://mytestdomain/v2/apikey?format=json")); homecoming true; }

c# .net windows-runtime async-await dotnet-httpclient

No comments:

Post a Comment