De Windows.Web.Http.HttpClient#GetAsync jette un incomplètes exception lorsque les informations d'identification non valides sont utilisés avec l'authentification de base
Je suis en train de travailler sur un Composant Windows Runtime qui effectue des appels d'API. Jusqu'à ce que plus tôt aujourd'hui, j'ai utilisé le HttpClient
et de modèles connexes de System.Net
mais basculé Windows.Web
au lieu de tirer parti de la WinRT ruisseaux.
Mis à part de changer la using
états, par l'échange d' HttpContent
à IHttpContent
et à l'aide de la WindowsRuntimeExtensions
changer mon IInputStream
à Stream
pour JSON.NET je n'ai pas eu à faire quelque chose de spécial. Cependant soudainement, 3 de mes 16 tests échouent, alors qu'auparavant tout fonctionnait.
Tous les 3 (intégration) des tests de valider que je reçois une réponse d'erreur lors de la connexion avec les informations d'identification non valides. Il y a d'autres tests comprennent l'exploitation forestière en tant que bien (mais avec des informations d'identification valides) et ils fonctionnent très bien. Le message d'erreur donné est de type AggregateException
et a comme message
System.AggregateException
: Une ou plusieurs erreurs se sont produites. --->System.Exception
: Élément introuvable.Une boîte de dialogue ne peut pas être affichée car le handle de fenêtre parent n'a pas été définie.
L'exception contient des valeurs HRESULT. Le outerexception a de la valeur -2146233088
qui correspond à 0x80131500
tandis que le innerexception a -2147023728
qui correspond à 0x80070490
. Ni de ceux qui sont connus code d'erreur sur la page MSDN.
La suite d'une enquête:
0x80131500
correspond àCOR_E_EXCEPTION
0x80070490
correspond à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
À l'origine de ma question a été formulée de manière quelque peu différente, car le problème semble être caché. J'ai trouvé que la demande d'OBTENIR par la HttpClient
renvoie à l'appelant au lieu d'attendre le résultat de l'appel (et d'exécuter le reste de la méthode).
Dans mon projet, l'exécution de la ligne de var data = await myHttpClient.GetAsync(url);
sera de retour à l'appel de la méthode avec un non-objet construit et les lignes suivantes qui viennent après GetAsync()
appel sont tout simplement pas exécuté.
Ajoutant .ConfigureAwait(false)
de l'empêcher de se retourner ne pas faire une différence.
La AggregateException
est levée lorsqu'un utilisateur essaie de se connecter avec des informations d'identification non valides. Pour une raison quelconque, le HttpClient
décide de lancer une exception puis, sans me donner un retour de la valeur que je pourrais utiliser. Le problème ici est qu'il ne me dise pas quel type d'exception: la capture de COMException
, TaskCanceledException
, AggregateException
et Exception
de déclencher le dernier.
J'ai aussi trouvé que les tests d'intégration ne fonctionne pas bien avec le multithread MSTest de l'environnement, de sorte que explique plusieurs autres tests ne que j'ai eu (mais a très bien fonctionné individuellement)
Moi aussi, enfin, un exemple qui illustre le problème (mais je ne peux pas fournir un service web qui prend basic 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;
}
}
L'exécution de ce code avec un mot de passe valide sera de retour true
alors qu'un mot de passe invalide va jeter un AggregateException
.
Droit maintenant, je suis en train de contourner le problème en attrapant un général Exception
autour de l'appel à GetAsync()
mais c'est très rudimentaire et j'aimerais savoir pourquoi ce incomplète exception est levée dans la première place.
- Pourriez-vous essayer de définir des informations d'authentification différentes:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", token);
- c'est une partie de la
System.Net.Http
espace de noms et ne sont pas compatibles avec laWindows.Web.Http.HttpClient
à moins que je sois donnant sur quelque chose. - À droite, vous êtes à l'aide de
Windows.Web
. Mon erreur. - Avez-vous essayé de créer un
HttpHandler
et les paramètres de sonCredentials
propriété, ensuite le passant àHttpClient
?var client = new HttpClient(handler)
- c'est
System.Net
ainsi. - Désolé, je ment un
IHttpFilter
: msdn.microsoft.com/en-us/library/windows/apps/... - J'ai fait un
IHttpFilter
mais je ne vois pas comment il peut faire une différence: il passe sur les informations à l'éventuelGetAsync
méthode; il n'a tout simplement dans une étape ultérieure. Configuration des informations d'identification dans le filtre n'a pas changé le résultat. - Je pense que je l'ai cette fois 🙂
- Le cas échéant, ajoutant simplement "Pragma:no-cache" à ma demande d'en-tête résolu ce problème pour moi.
Vous devez vous connecter pour publier un commentaire.
Après la reconstruction de votre exemple et de jouer, j'ai compris ce qui se passe.
La
GetAsync
méthode appelle la requête HTTP avec des informations d'identification non valides. Ce qui se passe, c'est que la demande qui revient essaye de regarder par une fenêtre dans laquelle vous pouvez entrer les informations d'identification correctes, mais ne pas en trouver un. Par conséquent, il jette unElement Not Found
lors de la recherche pour cette fenêtre.Cela peut être résolu par la création d'un
HttpBaseProtocolFilter
et le réglage de laAllowUI
propriétéfalse
puis en le passant à laHttpClient
:Réglage
AllowUI
surHttpBaseProtocolFilter
àfalse
va s'arrêter cette erreur.Si toutefois vous ne souhaitez qu'une boîte de dialogue à l'écran, ce qui permet à l'utilisateur d'entrer des informations d'identification, puis le web demande doit être démarré sur le thread de l'INTERFACE utilisateur.
Je pense que le problème est que l'exception est générée par votre appel à EnsureSuccessStatusCode.
Avez-vous essayez d'ajouter HttpResponseMessage classe EnsureSuccessStatusCode() la méthode et la vérifier.
http://msdn.microsoft.com/en-us/library/system.net.http.httpresponsemessage.ensuresuccessstatuscode.aspx
Après cette ligne:
await
point. Il n'a rien à voir avecEnsureSuccessStatusCode