使用async/await并从ASP.NET Web API方法返回Task<HttpResponseMessage>

10

我有一个像这样的可移植类库(PCL)方法:

public async Task<string> GetLineStatuses()
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
    using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
    {
        return response.GetResponseStream().ReadAllText();
    }
}

我的 ASP.NET Web Api 方法如下:

public async Task<HttpResponseMessage> Get()
{
    HttpResponseMessage response = new HttpResponseMessage();
    string statuses = await service.GetStatuses();
    response.Content = new StringContent(statuses);
    return response;
}

返回Web API中的Task有什么影响?这是允许的吗?我想使用await的唯一原因是为了使用可移植类库(PCL)。最佳实践是什么?我应该拥有一个同步版本和异步版本的方法吗?对性能、代码可读性和可维护性有什么影响?

如果我返回Task<string>而不是Task<HttpResponseMessage>,会产生相同的效果吗?


1
我相信.NET 4.5中的ASP.NET支持async方法,所以你的代码应该可以正常工作。你为什么要问这是否被允许?难道你没有尝试过吗? - svick
我也想知道性能、代码可读性和可维护性方面的影响是什么? - Muhammad Rehan Saeed
2个回答

5

在ASP.NET中,异步和等待是完全可行的。下面是Scott Handselman演示的视频:http://www.asp.net/vnext/overview/aspnet/async-and-await

“如果我返回Task<string>而不是Task<HttpResponseMessage>,会有相同的效果吗?”

我不太确定你的意思。任务就像对象的容器,因此Task<string>将包含您的字符串结果,Task<HttpResponseMessage>将包含您的HttpResponseMessage结果...您是否是这个意思?我认为两种方法都是完全可行的。如果只需要字符串,则使用它。没有必要返回更多。


在Web API中,您可以返回任何要序列化为内容的对象或返回HttpResponseMessage。这就是我的意思。 - Muhammad Rehan Saeed
1
我还是不明白你的意思。请记住,它不是返回一个字符串,而是一个Task<string>。在Task<string>.Result中的字符串可以作为内容呈现,但Task<string>本身不能。 - Pete
2
返回字符串和返回一个带有StringContent的HttpResponseMessage是两件不同的事情。如果你返回一个字符串,WebAPI将使用内容协商来查找可以序列化该字符串的格式化程序。如果你返回一个StringContent,那么该字符串将直接在响应中输出。但是,返回一个最终完成的Task<string>与直接返回该字符串对于WebAPI来说应该是等效的。 - Youssef Moussaoui

2

作为替代:

public static async Task<string> CallGET(string requestUri, string id = "")
{
    string responseData;
    using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
    {
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        Uri.TryCreate(new Uri(baseURI), $"{requestUri}{(string.IsNullOrEmpty(id) ? string.Empty : $"/{id}")}", out Uri fullRequestUri);
        using (var response = await client.GetAsync(fullRequestUri))
        {
            responseData = await response.Content.ReadAsStringAsync();
        }
        return responseData;
    }
}

最初的回答是:

这个调用将是:

var getListUsersResult = Utils.CallGET($"/v1/users").Result;
var resultset= JsonConvert.DeserializeObject(getListUsersResult, typeof(List<UsersDTO>)) as List<UsersDTO>;
UserDTO r = users.Where(d => d.Name.ToLower().Contains("test")).FirstOrDefault();

最初的回答
还有一个调用只返回一个项目的请求:
var getUser = Utils.CallGET($"/v1/users", $"{USER_ID}").Result;
var getUserResponse = JsonConvert.DeserializeObject(getUser, typeof(UserDTO)) as UserDTO;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接