Как сделать HTTP POST с помощью реактивного расширения на Windows Phone 7 - PullRequest
2 голосов
/ 14 августа 2011

Я нашел пример HTTP POST в msdn, но мне интересно, как я могу использовать здесь реактивные расширения.

using System;
 using System.Net;
 using System.IO;
 using System.Text; using System.Threading;

class HttpWebRequestBeginGetRequest
 {
     private static ManualResetEvent allDone = new ManualResetEvent(false);

    public static void Main(string[] args)
     {


        // Create a new HttpWebRequest object.
         HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/example.aspx");

        request.ContentType = "application/x-www-form-urlencoded";

        // Set the Method property to 'POST' to post data to the URI.
         request.Method = "POST";

        // start the asynchronous operation
         request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);

        // Keep the main thread from continuing while the asynchronous
         // operation completes. A real world application
         // could do something useful such as updating its user interface. 
        allDone.WaitOne();
     }

    private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
     {
         HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

        // End the operation
         Stream postStream = request.EndGetRequestStream(asynchronousResult);

        Console.WriteLine("Please enter the input data to be posted:");
         string postData = Console.ReadLine();

        // Convert the string into a byte array.
         byte[] byteArray = Encoding.UTF8.GetBytes(postData);

        // Write to the request stream.
         postStream.Write(byteArray, 0, postData.Length);
         postStream.Close();

        // Start the asynchronous operation to get the response
         request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
     }

    private static void GetResponseCallback(IAsyncResult asynchronousResult)
     {
         HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

        // End the operation
         HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
         Stream streamResponse = response.GetResponseStream();
         StreamReader streamRead = new StreamReader(streamResponse);
         string responseString = streamRead.ReadToEnd();
         Console.WriteLine(responseString);
         // Close the stream object
         streamResponse.Close();
         streamRead.Close();

        // Release the HttpWebResponse
         response.Close();
         allDone.Set();
     }
 }

Я пытаюсь использовать следующий код, но он не работает. Кто-нибудь может мне помочь в этом? Заранее спасибо -Peng

    return (from request in
                Observable.Return((HttpWebRequest)WebRequest.Create(new Uri(postUrl))).Catch(Observable.Empty<HttpWebRequest>())
                .Do(req =>
                        {
                            // Set up the request properties
                            req.Method = "POST";
                            req.ContentType = contentType;
                            req.UserAgent = userAgent;
                            req.CookieContainer = new CookieContainer();
                            Observable.FromAsyncPattern<Stream>(req.BeginGetRequestStream, req.EndGetRequestStream)()
                                .ObserveOnDispatcher()
                                .Subscribe(stream =>
                                        {
                                            stream.Write(formData, 0,
                                                         formData.Length);
                                            stream.Close();

                                        })
                                ;

                        })
            from response in
                Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse)().Catch(Observable.Empty<WebResponse>())
            from item in GetPostResponse(response.GetResponseStream()).ToObservable().Catch(Observable.Empty<string>())
            select item).ObserveOnDispatcher();

Редактировать: Чтобы было понятно, я хочу использовать rx для реализации той же логики в примере MSDN. в примере MSDN кажется, что сначала он делает асинхронный вызов для записи RequestStream, а затем в GetRequestStreamCallback запускает другой асинхронный вызов для получения ответа. Используя Rx, я могу создать 2 наблюдаемые 1. Observable.FromAsyncPattern (request.BeginGetRequestStream, request.EndGetRequestStream) () 2. Observable.FromAsyncPattern (request.BeginGetResponse, request.EndGetResponse) () Проблема в том, что вторая наблюдаемая зависит от результата первого, так как я могу сделать это в Rx? В первом методе наблюдения наблюдаемой для создания второй наблюдаемой? это хороший способ?

Ответы [ 2 ]

1 голос
/ 15 августа 2011

Ваша проблема заключается в том, что вы используете Do () здесь, вам нужно переместить GetRequestStream в вашу SelectMany (в вашу «из бла, из бла в» ...), поскольку имеет смысл только получить поток ответов после вы написали полный запрос.Прямо сейчас вы пытаетесь сделать оба одновременно.

1 голос
/ 15 августа 2011

Вот как я это делаю.Я настраиваю два асинхронных шаблона заранее, затем использую SelectMany, чтобы связать их вместе.
Я вырезал обработку ошибок и т. Д. Из этого кода, чтобы упростить его и показать только минимальный уровень для его работы.Вы должны добавить .Catch (), похожий на ваш собственный код, и если вы хотите получить больше, чем просто строку (скажем, код ответа), вам нужно будет создать класс / структуру для хранения всех битов данных.вам нужно и вернуть это вместо.

public IObservable<string> BeginPost(Uri uri, string postData) {
  var request = HttpWebRequest.CreateHttp(uri);
  request.Method = "POST";
  request.ContentType = "application/x-www-form-urlencoded";

  var fetchRequestStream = Observable.FromAsyncPattern<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream);
  var fetchResponse = Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse);
  return fetchRequestStream().SelectMany(stream => {
    using (var writer = new StreamWriter(stream)) writer.Write(postData);
    return fetchResponse();
  }).Select(result => {
    var response = (HttpWebResponse)result;
    string s = ""; 
    if (response.StatusCode == HttpStatusCode.OK) { 
      using (var reader = new StreamReader(response.GetResponseStream())) s = reader.ReadToEnd(); 
    }
    return s;
  });
}
...