2015-08-02 2 views
2

Я в процессе переноса моего приложения Windows 8.1 на Windows 10 UWP, но вызов PostAsync теперь выдает исключение.PostAsync бросает ошибку IRandomAccessStream при таргетинге на окна 10 UWP

Это точный код отлично работает при ориентации 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>", ""); 
} 

StackTrace

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() 
+0

Можете ли вы предоставить реализацию 'GetParameters()' и 'GetCredentials()'? Происходит ли ошибка, когда сервер не требует аутентификации? – kiewic

+0

@ kiewic, обязательно. Я добавил методы. Они ничего особенного. Что касается запроса на сервер, который не требует аутентификации. У меня нет удобного использования. Я нахожусь в безопасном апи. – Smeegs

ответ

2

Вы пытались использовать 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); 
    } 
} 
+0

Это не компиляция. HttpBaseProtocolFilter не имеет свойства «clientHandler» – Smeegs

+0

Неплохо, я хотел использовать 'ServerCredential' – kiewic

+0

Gotcha, я обновил эту часть, но класс HttpClient не имеет конструктора, который принимает объект HttpBaseProtocolFilter. – Smeegs

0

Его ошибка. Обходной путь заключается в использовании 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; 
    } 
} 
0

Нам нужно использовать библиотеку 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% для всех случаев использования.

Смежные вопросы