C# HttpClient PostAsync()从不返回响应

C# HttpClient PostAsync()从不返回响应,c#,asp.net,asynchronous,httpclient,C#,Asp.net,Asynchronous,Httpclient,我的问题与此非常相似。我有一个AuthenticationService类,它生成一个HttpClientPostAsync(),当我从ASP项目运行它时,它不会返回结果,但当我在控制台应用程序中实现它时,它工作得很好 class Program { static void Main() { AuthenticationService auth = new AuthenticationService(); User u = new User()

我的问题与此非常相似。我有一个
AuthenticationService
类,它生成一个
HttpClient
PostAsync()
,当我从ASP项目运行它时,它不会返回结果,但当我在控制台应用程序中实现它时,它工作得很好

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();
    }
}
这是我的身份验证服务类:

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;
    }
}
下面是我如何使用控制台应用程序测试该服务的一个示例,它运行得很好

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

由于您使用的是
.Result
,这将导致代码死锁。这在控制台应用程序中起作用的原因是控制台应用程序没有上下文,但ASP.NET应用程序有上下文(请参阅)。您应该在控制器中使用
Signin
方法
async
wait
调用
\u authenticationService.Authenticate
来解决死锁问题。

如果有人来了,需要查看代码,我只需将控制器更改为以下内容:

    /***
    *** 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);
    }
string responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
/***
***添加了异步和任务
****/
公共异步任务登录(用户)
{
//不需要令牌-我们正在请求令牌
//添加了wait和remove.Result()
Token Token=wait\u authenticationService.Authenticate(用户,apirls.sign);
返回重定向操作(“索引”、“仪表板”、token.user);
}

谢谢大家的快速回复

由于您正在使用
.Result
等待
等待
这将导致代码中出现死锁

您可以在
async
方法中使用
ConfigureAwait(false)
防止死锁

像这样:

    /***
    *** 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);
    }
string responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
您可以在任何可能的情况下使用
ConfigureAwait(false)
来表示不阻塞异步代码


ConfigureWait可以防止死锁。然而,这并不是它的真正意图,而且还有副作用(特别是在网站中,您可能无法访问来自HttpContext的信息)。在使用ConfigureAwait之前,最好对其进行更深入的研究。您在上面引用的消息来源也说:“使用ConfigureAwait(false)来避免死锁是一种危险的做法。您必须使用ConfigureAwait(false)对于阻塞代码调用的所有方法的传递闭包中的每个等待,包括所有第三方和第二方代码。使用ConfigureAwait(false)来避免死锁充其量只是一种攻击。)“本文很好地解释了何时应使用ConfigureAwait以及应注意的事项。