Using reactive extensions with WebRequest
October 14, 2010 1 Comment
I’ve recently started looking at the Rx library from Microsoft labs and it’s very interesting stuff, even though I have to admit I have a hard time wrapping my head around it. But it starts to sink in, bit by bit
When working with Windows Phone 7 development and my SharePoint library for WP7, I do a lot of asynchronous calls to web services. This code can often get a bit messy with all the callback methods so I tried to refactor it using reactive extensions and I am pretty pleased with the result:) I’m no expert on the field so I won’t guarantee that this is the best way to do it, but it works.
Here’s a sample of how to do a call to the Lists.asmx web service in SharePoint:
string Envelope = @"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<GetList xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">
<listName>{0}</listName>
</GetList>
</soap:Body>
</soap:Envelope>";
public void GetList(string server, string name, Action<XDocument> handler)
{
HttpWebRequest req = WebRequest.Create(string.Format("{0}/_vti_bin/lists.asmx", server)) as HttpWebRequest;
req.Headers["SOAPAction"] = "http://schemas.microsoft.com/sharepoint/soap/GetList";
req.ContentType = "text/xml; charset=utf-8";
req.Method = "POST";
var listRequest = (from request in Observable.FromAsyncPattern<Stream>(req.BeginGetRequestStream, req.EndGetRequestStream)().Do(stream =>
{
UTF8Encoding encoding = new UTF8Encoding();
string e = string.Format(Envelope, name);
byte[] bytes = encoding.GetBytes(e);
stream.Write(bytes, 0, bytes.Length);
stream.Close();
})
from response in Observable.FromAsyncPattern<WebResponse>(req.BeginGetResponse, req.EndGetResponse)()
select HandleResponse(response)).Subscribe(handler);
}
private void DoStuff(XDocument xml)
{
//parse the xml result here
}
private XDocument HandleResponse(WebResponse response)
{
HttpWebResponse res = response as HttpWebResponse;
if (res != null && res.StatusCode == HttpStatusCode.OK)
{
XDocument doc = XDocument.Load(response.GetResponseStream());
return doc;
}
return null;
}
Then of course we call the method:
GetList("http://spserver.com", "Pages", DoStuff);
In Windows Phone 7 we could add .ObserveOnDispatcher() before our .Subscribe() in the LINQ query so that the current Dispatcher is used when notifying observers.
We could also generalize the method so that it returns a IObservable<T> instead which we can subscribe to.
Wow!! I love what you are doing! I need to relook at screen toaster! Informative and interesting post!!!keep it up..