HttpClient PostAsync() never return response

2019-04-09 07:20发布

My problem is very similar to this question here. I have an authenticationService Class that makes an HttpClient PostAsync() and never return the result when I am running it from the ASP project, but when I implement it on a Console App it work just fine.

This is my Authentication Service Class.

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;
    }
}

And it is here where it hangs

HttpResponseMessage response = await _client.PostAsync(url, content);

Here is my Controller calling the service

 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();
    }

Here is an example of how I have been testing the service using a Console App and it runs just fine.

class Program
{
    static void Main()
    {

        AuthenticationService auth = new AuthenticationService();

        User u = new User()
        {
            email = "email@hotmail.com",
            password = "password123"
        };

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

        Console.Write("Content: " + newToken.user._id);

        Console.Read();

    }
}

Thank you in advance for your help.

3条回答
ら.Afraid
2楼-- · 2019-04-09 07:35

Since you are using .Result or .Wait or await this will end up causing a deadlock in your code.

you can use ConfigureAwait(false) in async methods for preventing deadlock

like this:

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

you can use ConfigureAwait(false) wherever possible for Don't Block Async Code .

查看更多
劳资没心,怎么记你
3楼-- · 2019-04-09 07:52

In case someone comes and needs to see code I just change the controller to something like this:

    /***
    *** 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);
    }

Thank you all for your quick response!

查看更多
家丑人穷心不美
4楼-- · 2019-04-09 07:56

Since you are using .Result this will end up causing a deadlock in your code. The reason this is working in a console application is because console applications don't have contexts, but ASP.NET apps do (see http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html). You should make the Signin method in your controller async and await the call to _authenticationService.Authenticate to resolve the deadlock issue.

查看更多
登录 后发表回答