回调永远不会来

时间:2016-03-17 21:02:41

标签: c# asynchronous asp.net-web-api

我有一个WebApi控制器,它以异步模式调用第三方API。 一切正常,现在我想在单独的动作方法中对结果进行排序。 现在,当我调用API时,在运行" await client.GetAsycn(...)"之后,结果的回调永远不会发生。在DAL中。我错过了什么?

这是我的 API控制器

    // GET api/lookup
    [ResponseType(typeof(RestaurantModel))]
    public async Task<IHttpActionResult> Get(string outcode)
    {
        if (string.IsNullOrEmpty(outcode)) throw new ArgumentNullException(nameof(outcode));

        var result = await _repository.GetRestaurantsByOutcode(outcode);

        return Ok(new RestaurantModel()
        {
            Result = result
        });
    }

    // GET api/sorted
    [System.Web.Http.Route("~/api/sorted")]
    public List<Restaurant> GetSorted(string outcode)
    {
        if (string.IsNullOrEmpty(outcode)) throw new ArgumentNullException(nameof(outcode));

        return _repository.GetSortedRestaurantsByOutcode(outcode);
    }

这是我的存储库,它使用一种新方法对结果进行排序:

public class RestaurantRepository : IRestaurantRepository
{
    private readonly IContext _context;

    public RestaurantRepository(IContext context)
    {
        _context = context;
    }

    public Task<ApiResult> GetRestaurantsByOutcode(string outcode)
    {
        return _context.GetRestaurantsByOutcode(outcode);
    }
    public List<Restaurant> GetSortedRestaurantsByOutcode(string outcode)
    {
        return _context.GetRestaurantsByOutcode(outcode).Result.Restaurants
            .OrderBy(x => x.Name).ToList();
    }
}

这是我的 DAL 来调用第三方API:

    public async Task<ApiResult> GetRestaurantsByOutcode(string outcode)
    {
        using (var client = new HttpClient())
        {
            ConfigureHttpClient(client);

            var response = await client.GetAsync(
                $"restaurants?q={WebUtility.UrlEncode(outcode)}");

            return response.IsSuccessStatusCode
                ? await response.Content.ReadAsAsync<ApiResult>()
                : null;
        }
    }

1 个答案:

答案 0 :(得分:0)

您有混合匹配,有​​时您使用async / await,有时则不使用async / await。 Async / await(可以并且默认情况下)确保调用在调用线程上恢复,从而产生上下文。您需要对代码进行对齐,以便在整个堆栈中使用async / await。否则你就会为自己制造僵局。

[System.Web.Http.Route("~/api/sorted")]
// missing async in signature (not good if you are calling it with await in your controller)
public async Task<List<Restaurant>> GetSorted(string outcode)
{
    if (string.IsNullOrEmpty(outcode)) throw new ArgumentNullException(nameof(outcode));
    // added await in call
    return await _repository.GetSortedRestaurantsByOutcode(outcode);
}

DAL

public class RestaurantRepository : IRestaurantRepository
{
    private readonly IContext _context;

    public RestaurantRepository(IContext context)
    {
        _context = context;
    }
    // added async and await
    public async Task<ApiResult> GetRestaurantsByOutcode(string outcode)
    {
        return await _context.GetRestaurantsByOutcode(outcode);
    }
    // added async and await
    public async Task<List<Restaurant>> GetSortedRestaurantsByOutcode(string outcode)
    {
        // here you were not using await but then using result even though you were calling into a method marked as async which in turn used an await. this is where you deadlocked but this the fix.
        return (await _context.GetRestaurantsByOutcode(outcode)).Restaurants
            .OrderBy(x => x.Name).ToList();
    }
}