2016-05-25 1 views
3

У меня есть проект веб-API, который настроен для CORS и реализует [Авторизовать] на одном из APICконтроллеров. Я могу получить доступ к API от клиента WPF, когда я удаляю [Authorize], но когда он на месте, вызов, похоже, затеряется. Это то, что у меня есть, чтобы запросить токен.Доступ к защищенному веб-API от клиента WPF

В коде WPF позади

internal void RefreshRecentFilesList() 
    { 
     //Get the token 
     var token = GetAPIToken(email, password, "http://localhost:50006").Result; 
     MessageBox.Show(token); 
    } 

    private static async Task<string> GetAPIToken(string userName, string password, string apiBaseUri) 
    { 
     using (var client = new HttpClient()) 
     { 
      //setup client 
      client.BaseAddress = new Uri(apiBaseUri); 
      client.DefaultRequestHeaders.Accept.Clear(); 
      client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
      //client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token.AccessToken); 

      //setup login data 
      var formContent = new FormUrlEncodedContent(new[] 
      { 
      new KeyValuePair<string, string>("grant_type", "password"), 
      new KeyValuePair<string, string>("username", userName), 
      new KeyValuePair<string, string>("password", password), 
      }); 

      //send request 
      HttpResponseMessage responseMessage = await client.PostAsync("/Token", formContent); 

      //get access token from response body 
      var responseJson = await responseMessage.Content.ReadAsStringAsync(); 
      var jObject = JObject.Parse(responseJson); 
      return jObject.GetValue("access_token").ToString(); 
     } 
    } 

В проекте Web API WebAPIConfig.cs

 //Enable CORS 
     var cors = new EnableCorsAttribute("*", "*", "GET"); 
     config.EnableCors(cors); 

В контроллере

[HttpGet] 
    //[Authorize] 
    public List<FileInfo> GetFileTypes() 
    { 
     List<FileInfo> fileInfos = new List<FileInfo>(); 
     ... 

API В StartAuth.cs

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>(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 PathString("/Token"), 
      Provider = new ApplicationOAuthProvider(PublicClientId), 
      AuthorizeEndpointPath = new PathString("/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); 

Когда я запускаю WPF и просматриваю код, он попадает на строку запроса отправки, а затем просто зависает.

Может ли кто-нибудь указать мне в правильном направлении, пожалуйста?

Большое спасибо

ответ

2

Я думаю, что основной кандидат на ваш вопрос этой линия:

var token = GetAPIToken(email, password, "http://localhost:50006").Result; 

Вы звоните в async метод, а затем вы ждете его результата синхронно: это приведет к тупикам , Никогда не делай этого.

Вместо этого превратите свой метод (и весь стек вызовов) асинхронным. Если вы находитесь внутри WPF, вы почти наверняка называете этот метод каким-то обратным вызовом обработчика событий. Эти обратные вызовы поддерживают async (даже если они должны вернуть void).

Измените свой код на нечто похожее на это, а затем попробуйте еще раз (при условии, это событие обработчик обратного вызова):

private async void Form_Load(object sender, EventArgs e) 
{ 
    await RefreshRecentFilesList(); 
} 

internal async Task RefreshRecentFilesList() 
{ 
    //Get the token 
    var token = await GetAPIToken(email, password, "http://localhost:50006"); 
    MessageBox.Show(token); 
} 

Ссылки:
Why does this async action hang?
How to call asynchronous method from synchronous method in C#?

+0

Благодарим за помощь, это было сочетание синхронных и асинхронных вызовов, вызывающих тупик. Я переработал свой код на основе вашего предложения, и теперь у меня есть полностью функционирующий клиент WPF, который вызывает защищенные методы Web API. – RichK

+0

@RichK Добро пожаловать, но, пожалуйста, помните, чтобы всегда голосовать и/или отмечать как выбранный ответ, если он решил вашу проблему здесь, в stackoverflow. –

+0

Я пометил ответ как решенный. Я не могу голосовать, мне нужно больше очков репутации :-( – RichK

0

дополняют друг друга Федерико Решения Dipuma - это вызов Form_Load из конструктора с использованием

this.Loaded += new RoutedEventHandler(Form_Load); 
+0

Что делать? –

+0

если вы используете окно и класс «code behind», если у вас есть эта функция без «вызова», инструкции не будут выполнены код выше будет добавлен к маршрутизируемому событию и будет выполнен после полной загрузки страницы –

+0

Извините, я все еще не понимаю. Поскольку принятый ответ правильный, я не вижу, чтобы это было полезно.#NoOffense –

Смежные вопросы