asp.net HttpClient PostAsync()从不返回响应

7ivaypg9  于 2023-04-13  发布在  .NET
关注(0)|答案(3)|浏览(373)

我的问题与这里的question非常相似。我有一个AuthenticationService类,它生成一个HttpClientPostAsync(),当我从ASP项目运行它时,它从不返回结果,但当我在Console应用程序中实现它时,它工作得很好。
这是我的身份验证服务类:

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);
下面是我的Controller调用服务:

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@hotmail.com",
            password = "password123"
        };

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

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

irtuqstp1#

由于您使用的是.Result,这最终会导致代码中出现死锁。这在控制台应用程序中有效的原因是因为控制台应用程序没有上下文,但ASP.NET应用程序有上下文(请参阅Stephen Cleary's Don't Block on Async Code)。您应该在控制器async中使用Signin方法,并将await作为对_authenticationService.Authenticate的调用来解决死锁问题。

qpgpyjmq

qpgpyjmq2#

由于你使用的是.Result.Waitawait,这最终会导致代码中出现死锁
你可以在async方法中使用ConfigureAwait(false)防止死锁
就像这样:

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

您可以在任何可能的情况下使用ConfigureAwait(false)来实现“不阻止异步代码”。

vxbzzdmp

vxbzzdmp3#

如果有人来看代码,我只需要将控制器更改为如下所示:

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

感谢大家的快速回复!

相关问题