web-dev-qa-db-ja.com

HttpClient PostAsync()が応答を返すことはありません

私の問題はこれに非常に似ています 質問 ここに。 AuthenticationServicePostAsync()を作成するHttpClientクラスがあり、ASPプロジェクトから実行しているときに結果を返さないが、コンソールアプリに実装すると正常に動作します。

これは私の認証サービスクラスです:

_public class AuthenticationService : BaseService
{
    public async Task<Token> Authenticate (User user, string url)
    {
        string json = JsonConvert.SerializeObject(user);
        StringContent content = new StringContent(json, Encoding.UTF8, "application/json");

        HttpResponseMessage response = await _client.PostAsync(url, content);
        string responseContent = await response.Content.ReadAsStringAsync();
        Token token = JsonConvert.DeserializeObject<Token>(responseContent);

        return token;
    }
}
_

ハングする場所はここです:HttpResponseMessage response = await _client.PostAsync(url, content);

ここに私のコントローラーがサービスを呼び出しています:

_public ActionResult Signin(User user)
{
    // no token needed to be send - we are requesting one
    Token token =  _authenticationService.Authenticate(user, ApiUrls.Signin).Result;
    return View();
}
_

これは、コンソールアプリを使用してサービスをテストしている例です。問題なく実行されます。

_class Program
{
    static void Main()
    {
        AuthenticationService auth = new AuthenticationService();

        User u = new User()
        {
            email = "[email protected]",
            password = "password123"
        };

        Token newToken = auth.Authenticate(u, ApiUrls.Signin).Result;

        Console.Write("Content: " + newToken.user._id);
        Console.Read();
    }
}
_
13
Erik

.Resultを使用しているため、これによりコードでデッドロックが発生します。これがコンソールアプリケーションで機能するのは、コンソールアプリケーションにコンテキストがないためですが、ASP.NETアプリにはあります( http://blog.stephencleary.com/2012/07/dont-block-onを参照)。 -async-code.html )。コントローラーのSigninメソッドを非同期にし、_authenticationService.Authenticateの呼び出しを待って、デッドロックの問題を解決する必要があります。

17
Josh Dammann

誰かが来てコードを見る必要がある場合は、コントローラを次のように変更します:

    /***
    *** Added async and Task<ActionResult>
    ****/
    public async Task<ActionResult> Signin(User user)
    {
        //no token needed - we are requesting one
        // added await and remove .Result()
        Token token =  await _authenticationService.Authenticate(user, ApiUrls.Signin);

        return RedirectToAction("Index", "Dashboard", token.user);
    }

迅速な対応ありがとうございました!

5
Erik

_.Result_または_.Wait_またはawaitを使用しているため、コードにdeadlockが発生します。

asyncメソッドでConfigureAwait(false)を使用してデッドロックを防止

このような:

_string responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
_

[非同期コードをブロックしない]では、可能な限りConfigureAwait(false)を使用できます。

2
Hasan Fathi