使用Async和Await转换普通的Http Post Web请求

我如何使用Async / Await模式转换我的传统HttpWebRequest“POST”调用,这里有我附加我当前的代码,任何人请帮我转换此代码使用Windows Phone 8的Async / Await模式。

public void GetEnvironmentVariables(Action getResultCallback, Action getErrorCallback) { CredentialsCallback = getResultCallback; ErrorCallback = getErrorCallback; var uri = new Uri(BaseUri); var request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "POST"; request.ContentType = "application/json"; var jsonObject = new JObject { new JProperty("apiKey",_api), new JProperty("affiliateId",_affid), }; var serializedResult = JsonConvert.SerializeObject(jsonObject); byte[] requestBody = Encoding.UTF8.GetBytes(serializedResult); request.BeginGetRequestStream(GetRequestStreamCallback, new object[] { request, requestBody }); } private void GetRequestStreamCallback(IAsyncResult asynchronousResult) { var request = (HttpWebRequest)((object[])asynchronousResult.AsyncState)[0]; using (var postStream = request.EndGetRequestStream(asynchronousResult)) { var byteArray = (byte[])((object[])asynchronousResult.AsyncState)[1]; // Write to the request stream. postStream.Write(byteArray, 0, byteArray.Length); } request.BeginGetResponse(GetResponseCallback, request); } private void GetResponseCallback(IAsyncResult asynchronousResult) { var request = (HttpWebRequest)asynchronousResult.AsyncState; try { var response = (HttpWebResponse)request.EndGetResponse(asynchronousResult); if (response != null) { var reader = new StreamReader(response.GetResponseStream()); string responseString = reader.ReadToEnd(); Credentails = JsonConvert.DeserializeObject(responseString); if (Credentails != null && string.IsNullOrEmpty(Credentails.Err)) CredentialsCallback(Credentails); else { if (Credentails != null) ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err))); } } } catch (WebException we) { var reader = new StreamReader(we.Response.GetResponseStream()); string responseString = reader.ReadToEnd(); Debug.WriteLine(responseString); ErrorCallback(we); } } 

由于Windows Phone 8似乎不提供您需要的TAP方法,例如GetRequestStreamAsync ,首先要做的是编写一个小包装器来为自己提供:

 public static class WebRequestAsyncExtensions { public static Task GetRequestStreamAsync(this WebRequest request) { return Task.Factory.FromAsync( request.BeginGetRequestStream, request.EndGetRequestStream, null); } public static Task GetResponseAsync(this WebRequest request) { return Task.Factory.FromAsync( request.BeginGetResponse, request.EndGetResponse, null); } } 

请注意Task.Factory.FromAsync的使用 – 这是获取围绕基于APM的异步API(例如WebRequest提供的异步API)的awaitTask.Factory.FromAsync友好包装器的首选方法。 这比使用其他人建议的Task.Factory.StartNew更有效,因为这会启动一个新线程,而这不需要。

有了这个,您现在可以像在可以使用这些TAP样式方法的平台上那样编写代码(例如,Windows 8商店应用程序,桌面应用程序等):

 public async Task GetEnvironmentVariablesAsync(Action getResultCallback, Action getErrorCallback) { CredentialsCallback = getResultCallback; ErrorCallback = getErrorCallback; var uri = new Uri(BaseUri); var request = (HttpWebRequest) WebRequest.Create(uri); request.Method = "POST"; request.ContentType = "application/json"; var jsonObject = new JObject { new JProperty("apiKey",_api), new JProperty("affiliateId",_affid), }; var serializedResult = JsonConvert.SerializeObject(jsonObject); byte[] requestBody = Encoding.UTF8.GetBytes(serializedResult); // ASYNC: using awaitable wrapper to get request stream using (var postStream = await request.GetRequestStreamAsync()) { // Write to the request stream. // ASYNC: writing to the POST stream can be slow await postStream.WriteAsync(requestBody, 0, requestBody.Length); } try { // ASYNC: using awaitable wrapper to get response var response = (HttpWebResponse) await request.GetResponseAsync(); if (response != null) { var reader = new StreamReader(response.GetResponseStream()); // ASYNC: using StreamReader's async method to read to end, in case // the stream i slarge. string responseString = await reader.ReadToEndAsync(); Credentails = JsonConvert.DeserializeObject(responseString); if (Credentails != null && string.IsNullOrEmpty(Credentails.Err)) CredentialsCallback(Credentails); else { if (Credentails != null) ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err))); } } } catch (WebException we) { var reader = new StreamReader(we.Response.GetResponseStream()); string responseString = reader.ReadToEnd(); Debug.WriteLine(responseString); ErrorCallback(we); } } 

注意带有// ASYNC:四行// ASYNC:注释 – 这些显示了我进行更改的位置。 我已经将你的方法折叠为一个,因为这是a)可能一旦你使用asyncawait和b)比尝试使用状态参数从一个方法传递到下一个方法容易得多。

请注意,其中第二个和第四个实际上会使您以前同步执行的操作异步化:将数据写入请求流,并从响应流中读取数据。 对于小的请求,这可能无关紧要,但如果正在传输大量数据,则对WriteReadToEnd的同步调用可能会阻塞。 幸运的是,尽管Windows Phone 8似乎缺少WebRequest上的TAP方法,但它确实在StreamStreamReader上提供了这些方法,因此无需编写任何扩展方法即可实现。

我是社区的新手,所以这是我的第一篇文章。 在这种情况下,您可以使用通用任务返回任何类型。 这对我来说过去很有用。

服务器端

 public class MyController : ApiController { public Task PostAsync() { return Task.Factory.StartNew(() => { return "populate me with any type and data, but change the type in the response signature."; }); } } 

客户端

 public class HomeController : Controller { public Task Index() { return Task.Factory.StartNew(() => { var model = "use a provider, get some data, or something"; return View(model); }); } } 

这应该做的工作:

  public async void GetEnvironmentVariables(Action getResultCallback, Action getErrorCallback) { CredentialsCallback = getResultCallback; ErrorCallback = getErrorCallback; var uri = new Uri(BaseUri); var request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "POST"; request.ContentType = "application/json"; var jsonObject = new JObject { new JProperty("apiKey", _api), new JProperty("affiliateId", _affid), }; var serializedResult = JsonConvert.SerializeObject(jsonObject); var requestBody = Encoding.UTF8.GetBytes(serializedResult); var requestStream = request.GetRequestStream(); requestStream.Write(requestBody, 0, requestBody.Length); await GetResponse(request); } private async Task GetResponse(WebRequest request) { Stream resStream = null; try { var response = await request.GetResponseAsync(); if (response == null) { return; } resStream = response.GetResponseStream(); if (resStream == null) { return; } var reader = new StreamReader(resStream); var responseString = await reader.ReadToEndAsync(); Credentails = JsonConvert.DeserializeObject(responseString); if (Credentails != null && string.IsNullOrEmpty(Credentails.Err)) { CredentialsCallback(Credentails); } else { if (Credentails != null) { ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err))); } } } catch (WebException we) { if (resStream != null) { var reader = new StreamReader(resStream); var responseString = reader.ReadToEnd(); Debug.WriteLine(responseString); } ErrorCallback(we); } }