是否可以通过IObservable接口返回HttpWebRequest POST方法的结果

时间:2010-12-01 11:03:18

标签: .net silverlight httpwebrequest system.reactive

我正在尝试使用单一方法通过Reactive接口IObservable返回HttpWebRequest POST方法的结果。我已经设法使用以下代码为GET方法执行此操作:

var request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(url);
  request.Method = method;
  request.Accept = GetHttpType();
  request.CookieContainer = new CookieContainer();

   return Observable.FromAsyncPattern(request.BeginGetResponse, ar => ProcessResponse(method, ar, request))()
                    .Select(r => r);

但我不确定如何通过读取HTTP POST操作所需的响应流来将写入请求流的异步观察者链接在一起。如何连接以下变量obs1& obs2一起,以便我可以返回obs2?

var request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(url);
var type = GetHttpType();
request.Method = method;
request.Accept = type;
request.ContentType = type;
request.CookieContainer = new CookieContainer();

var data = Serialize(requestResource);

var obs1 = Observable.FromAsyncPattern(request.BeginGetRequestStream, ar1 => ProcessRequest(method, data, ar1, request))

var obs2 = Observable.FromAsyncPattern(request.BeginGetResponse, ar2 => ProcessResponse(method, ar2, request))();

// How do I connect obs1 And obs2 together...

return obs2;

我原以为以下情况应该有效但是'ProcessResponse'方法永远不会被调用,有人知道为什么吗?

 var obs1 = Observable.FromAsyncPattern(request.BeginGetRequestStream, ar1 => ProcessRequest(method, data, ar1, request))();
 var obs2 = Observable.FromAsyncPattern(request.BeginGetResponse, ar2 => ProcessResponse(method, ar2, request));

 return obs1.SelectMany(a => obs2(), (a, b) => b);

3 个答案:

答案 0 :(得分:2)

FromAsyncPattern期望BeginAction和EndAction方法都作为参数。我认为你在寻找的是:

HttpWebRequest httpRequest = 
    (HttpWebRequest)HttpWebRequest.Create("http://www.stackoverflow.com");

httpRequest.Method = "POST";

var requestAsync = Observable.FromAsyncPattern<Stream>(
    httpRequest.BeginGetRequestStream, httpRequest.EndGetRequestStream);

var responseAsync = Observable.FromAsyncPattern<WebResponse>(
    httpRequest.BeginGetResponse, httpRequest.EndGetResponse);

requestAsync()
    .SelectMany(requestStream =>
    {
        // requestStream.Write

        return responseAsync();
    })
    .Subscribe(webResponse =>
    {
        // complete
    });

如果您对请求流的写入是异步的,我可以相应地更新示例。

答案 1 :(得分:1)

好的,我现在知道了。首先是代码,然后解释:

byte[] buffer1 = Encoding.UTF8.GetBytes(data); // assume post data is utf-8 encoded

var obs1 = Observable.FromAsyncPattern(request.BeginGetRequestStream, ar1 => request.EndGetRequestStream(ar1));

return from stream in obs1()
       let obs2 = Observable.FromAsyncPattern((ac, state) => stream.BeginWrite(buffer1, 0, buffer1.Length, ac, state), ar2 => stream.EndWrite(ar2))
       from _ in obs2()
       let obs3 = Observable.FromAsyncPattern(request.BeginGetResponse, ar2 => request.EndGetResponse(ar2))
       from response in obs3()
       select response;

您使用SelectMany处于正确的轨道上,但我发现常规的LINQ语法更具可读性。我也通过异步发布改进了你的例子,即以异步方式写入上传流。基本上第一个from给我们一个流,我们在第一个let中用于异步帖子,第三个将忽略上传的结果(因此奇怪地命名为变量'_'),最后是简单订阅的最后一个得到反应的结果。

我必须承认,我发现这个例子延伸了Observable的概念。我认为使用Task可以获得更好的结果和更易读的代码,甚至可能在C#5中使用新的异步支持更好的结果(但除了CPT之外不可用)。

答案 2 :(得分:-1)

或许

obs1.Concat(obs2)