指向Windows 10 UWP时PostAsync抛出IRandomAccessStream错误

我正在将Windows 8.1应用程序移植到Windows 10 UWP,但调用PostAsync现在会抛出exception。

这个确切的代码在定位8.1时非常有效,但是当我以Windows 10 UWP为目标时,它会引发以下exception:

This IRandomAccessStream does not support the GetInputStreamAt method because it requires cloning and this stream does not support cloning.

  public async void TestPost() { var parameters = GetParameters(); var formattedData = new FormUrlEncodedContent(parameters); using (var clientHandler = new HttpClientHandler { Credentials = GetCredentials() }) { using (var httpClient = new HttpClient(clientHandler)) { var response = await httpClient.PostAsync(postUrl, formattedData); } } } private Dictionary GetParameters() { var parameters = new Dictionary(); parameters["grant_type"] = "url"; parameters["device_id"] = "unique key"; parameters["redirect_uri"] = "redirect url"; return parameters; } public static NetworkCredential GetCredentials() { return new NetworkCredential("", ""); } 

堆栈跟踪

  at System.IO.NetFxToWinRtStreamAdapter.ThrowCloningNotSuported(String methodName) at System.IO.NetFxToWinRtStreamAdapter.GetInputStreamAt(UInt64 position) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.Http.HttpHandlerToFilter.d__1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.Http.HttpClientHandler.d__1.MoveNext() 

您是否尝试过使用Windows.Web.Http.HttpClient

 // using Windows.Web.Http; // using Windows.Web.Http.Filters; var parameters = GetParameters(); var formattedData = new HttpFormUrlEncodedContent(parameters); using (var clientHandler = new HttpBaseProtocolFilter()) { clientHandler.ServerCredential = GetCredentials(); using (var httpClient = new HttpClient(clientHandler)) { var response = await httpClient.PostAsync(postUrl, formattedData); } } 

这是一个错误。 解决方法是使用Windows.Web

 using Windows.Web.Http; using Windows.Web.Http.Filters; using Windows.Web.Http.Headers; ///  /// Performs the post asynchronous. ///  /// The generic type parameter. /// The URI. /// The object to post. /// The response message. private static async Task PerformPostAsyncstring uri, object objectToPost) { HttpResponseMessage response = null; // Just add default filter (to enable enterprise authentication) HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter(); using (HttpClient client = HttpService.CreateHttpClient(filter)) { // Now create the new request for the post HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(uri)); if (objectToPost != null) { // Frist get the bytes byte[] bytes = UTF8Encoding.UTF8.GetBytes(JsonHelper.Serialize(objectToPost)); // Now create the HttpBufferContent from the bytes and set the request content IHttpContent content = new HttpBufferContent(bytes.AsBuffer()); content.Headers.ContentType = HttpMediaTypeHeaderValue.Parse(HttpService.JsonMediaType); request.Content = content; } // Now complete the request response = await client.SendRequestAsync(request); } return response; } ///  /// Creates the HTTP client. ///  /// The filter. /// HTTP client. private static HttpClient CreateHttpClient(HttpBaseProtocolFilter filter = null) { HttpClient client = new HttpClient(filter); client.DefaultRequestHeaders.Accept.Add(new HttpMediaTypeWithQualityHeaderValue(HttpService.JsonMediaType)); return client; } } 

我们需要将PCL System.Net.Http库用于跨平台,因此我们不能只是将所有内容交换使用特定于平台的库。 我们最终为特定的问题案例使用了不同的HttpMessageHandler。 该处理程序将实际调用委托给Windows.Web.Http库。

 ///  /// A System.Net.Http message handler that delegates out to Windows.Web.Http.HttpClient. ///  public class WindowsHttpMessageHandler : HttpMessageHandler { private const string UserAgentHeaderName = "User-Agent"; protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { Windows.Web.Http.HttpClient client = new Windows.Web.Http.HttpClient(); Windows.Web.Http.HttpRequestMessage webRequest = new Windows.Web.Http.HttpRequestMessage { Method = ConvertMethod(request.Method), RequestUri = request.RequestUri, Content = await ConvertRequestContentAsync(request.Content).ConfigureAwait(false), }; CopyHeaders(request.Headers, webRequest.Headers); Windows.Web.Http.HttpResponseMessage webResponse = await client.SendRequestAsync(webRequest) .AsTask(cancellationToken) .ConfigureAwait(false); HttpResponseMessage response = new HttpResponseMessage { StatusCode = ConvertStatusCode(webResponse.StatusCode), ReasonPhrase = webResponse.ReasonPhrase, Content = await ConvertResponseContentAsync(webResponse.Content).ConfigureAwait(false), RequestMessage = request, }; CopyHeaders(webResponse.Headers, response.Headers); return response; } private static void CopyHeaders(HttpRequestHeaders input, Windows.Web.Http.Headers.HttpRequestHeaderCollection output) { foreach (var header in input) { output.Add(header.Key, GetHeaderValue(header.Key, header.Value)); } } private static void CopyHeaders(HttpContentHeaders input, Windows.Web.Http.Headers.HttpContentHeaderCollection output) { foreach (var header in input) { output.Add(header.Key, GetHeaderValue(header.Key, header.Value)); } } private static void CopyHeaders(Windows.Web.Http.Headers.HttpContentHeaderCollection input, HttpContentHeaders output) { foreach (var header in input) { if (!string.Equals(header.Key, "Expires", StringComparison.OrdinalIgnoreCase) || header.Value != "-1") { output.Add(header.Key, header.Value); } } } private static void CopyHeaders(Windows.Web.Http.Headers.HttpResponseHeaderCollection input, HttpResponseHeaders output) { foreach (var header in input) { output.Add(header.Key, header.Value); } } private static string GetHeaderValue(string name, IEnumerable value) { return string.Join(string.Equals(name, UserAgentHeaderName, StringComparison.OrdinalIgnoreCase) ? " " : ",", value); } private static Windows.Web.Http.HttpMethod ConvertMethod(HttpMethod method) { return new Windows.Web.Http.HttpMethod(method.ToString()); } private static async Task ConvertRequestContentAsync(HttpContent content) { if (content == null) { return null; } Stream contentStream = await content.ReadAsStreamAsync().ConfigureAwait(false); var result = new Windows.Web.Http.HttpStreamContent(contentStream.AsInputStream()); CopyHeaders(content.Headers, result.Headers); return result; } private static async Task ConvertResponseContentAsync(Windows.Web.Http.IHttpContent content) { var responseStream = await content.ReadAsInputStreamAsync(); var result = new StreamContent(responseStream.AsStreamForRead()); CopyHeaders(content.Headers, result.Headers); return result; } private static HttpStatusCode ConvertStatusCode(Windows.Web.Http.HttpStatusCode statusCode) { return (HttpStatusCode)(int)statusCode; } } 

虽然因为我们只需要几次调用,但并未对所有用例进行100%测试。