Obtenir le jeton ASP.NET MVC5 WebAPI échoue parfois

Obtenir le jeton ASP.NET MVC5 WebAPI échoue parfois

Code

ssortingng GetAPITokenSync(ssortingng username, ssortingng password, ssortingng apiBaseUri) { var token = ssortingng.Empty; using (var client = new HttpClient()) { client.BaseAddress = new Uri(apiBaseUri); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.Timeout = TimeSpan.FromSeconds(60); //setup login data var formContent = new FormUrlEncodedContent(new[] { new KeyValuePair("grant_type", "password"), new KeyValuePair("username", username), new KeyValuePair("password", password), }); //send request Task t = Task.Run(() => { HttpResponseMessage responseMessage = client.PostAsync("/Token", formContent).Result; var responseJson = responseMessage.Content.ReadAsSsortingngAsync().Result; var jObject = JObject.Parse(responseJson); token = jObject.GetValue("access_token").ToSsortingng(); }); t.Wait(); t.Dispose(); t = null; GC.Collect(); return token; } } 

Erreur

Une ou plusieurs erreurs sont survenues. —> System.AggregateException: une ou plusieurs erreurs se sont produites. —> System.Threading.Tasks.TaskCanceledException: une tâche a été annulée.
— Fin de trace de stack d’exception interne — at System.Threading.Tasks.Task.ThrowIfExceptional (Boolean includeTaskCanceled Exceptions) at System.Threading.Tasks.Task 1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task 1.get_Result ()

La méthode de connexion WebAPi est par défaut aucune modification.

 [HttpPost] [AllowAnonymous] [Route("Login")] public HttpResponseMessage Login(ssortingng username, ssortingng password) { try { var identityUser = UserManager.Find(username, password); if (identityUser != null) { var identity = new ClaimsIdentity(Startup.OAuthOptions.AuthenticationType); identity.AddClaim(new Claim(ClaimTypes.Name, username)); AuthenticationTicket ticket = new AuthenticationTicket(identity, new AuthenticationProperties()); var currentUtc = new SystemClock().UtcNow; ticket.Properties.IssuedUtc = currentUtc; ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(1440)); var token = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket); var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ObjectContent(new { UserName = username, ExternalAccessToken = token }, Configuration.Formatters.JsonFormatter) }; return response; } } catch (Exception) { } return new HttpResponseMessage(HttpStatusCode.BadRequest); } } 

La classe de démarrage est par défaut aucune modification

  public partial class Startup { public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; } public static ssortingng PublicClientId { get; private set; } public void ConfigureAuth(IAppBuilder app) { // Configure the db context and user manager to use a single instance per request app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext(ApplicationUserManager.Create); // Enable the application to use a cookie to store information for the signed in user // and to use a cookie to temporarily store information about a user logging in with a third party login provider app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); // Configure the application for OAuth based flow PublicClientId = "self"; OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathSsortingng("/Token"), Provider = new ApplicationOAuthProvider(PublicClientId), AuthorizeEndpointPath = new PathSsortingng("/api/Account/ExternalLogin"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), // In production mode set AllowInsecureHttp = false AllowInsecureHttp = true }; // Enable the application to use bearer tokens to authenticate users app.UseOAuthBearerTokens(OAuthOptions); } } 

Un indice?

Il est difficile de dire avec certitude, mais la façon dont vous bloquez les appels HttpClient ne peut pas vous aider. HttpClient est une bibliothèque async seulement; vous pouvez avoir une situation de blocage. Je suggère de supprimer tous les .Result et .Wait() et de tout écrire de manière asynchrone, en utilisant async/await . Et votre Task.Run ne donne rien, alors ça devrait aller.

Je comprends que c’est l’application Topshelf transférée depuis une application console. Je ne connais pas très bien Topshelf, mais je suppose que, comme les applications pour console, vous devez bloquer quelque part ou votre application va simplement quitter. L’endroit pour le faire est tout en haut – le point d’entrée de l’application.

Cela illustre le modèle, avec une réécriture de votre méthode GetApiToken :

 // app entry point - the only place you should block void Main() { MainAsync().Wait(); } // the "real" starting point of your app logic. do everything async from here on async Task MainAsync() { ... var token = await GetApiTokenAsync(username, password, apiBaseUri); ... } async Task GetApiTokenAsync(ssortingng username, ssortingng password, ssortingng apiBaseUri) { var token = ssortingng.Empty; using (var client = new HttpClient()) { client.BaseAddress = new Uri(apiBaseUri); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.Timeout = TimeSpan.FromSeconds(60); //setup login data var formContent = new FormUrlEncodedContent(new[] { new KeyValuePair("grant_type", "password"), new KeyValuePair("username", username), new KeyValuePair("password", password), }); //send request HttpResponseMessage responseMessage = await client.PostAsync("/Token", formContent); var responseJson = await responseMessage.Content.ReadAsSsortingngAsync(); var jObject = JObject.Parse(responseJson); token = jObject.GetValue("access_token").ToSsortingng(); return token; } }