[英]PostAsync throwing IRandomAccessStream error when targeting windows 10 UWP
我正在将我的 Windows 8.1 应用程序移植到 Windows 10 UWP,但现在调用PostAsync
会引发异常。
当以 8.1 为目标时,这个确切的代码可以完美运行,但是当我以 Windows 10 UWP 为目标时,它会引发以下异常:
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<string, string> GetParameters()
{
var parameters = new Dictionary<string, string>();
parameters["grant_type"] = "url";
parameters["device_id"] = "unique key";
parameters["redirect_uri"] = "redirect url";
return parameters;
}
public static NetworkCredential GetCredentials()
{
return new NetworkCredential("<secret key>", "");
}
堆栈跟踪
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.<SendAsync>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.<SendAsync>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;
/// <summary>
/// Performs the post asynchronous.
/// </summary>
/// <typeparam name="T">The generic type parameter.</typeparam>
/// <param name="uri">The URI.</param>
/// <param name="objectToPost">The object to post.</param>
/// <returns>The response message.</returns>
private static async Task<HttpResponseMessage> PerformPostAsync<T>string 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;
}
/// <summary>
/// Creates the HTTP client.
/// </summary>
/// <param name="filter">The filter.</param>
/// <returns>HTTP client.</returns>
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 库。
/// <summary>
/// A System.Net.Http message handler that delegates out to Windows.Web.Http.HttpClient.
/// </summary>
public class WindowsHttpMessageHandler : HttpMessageHandler
{
private const string UserAgentHeaderName = "User-Agent";
protected override async Task<HttpResponseMessage> 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<string> 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<Windows.Web.Http.IHttpContent> 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<HttpContent> 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% 测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.