Created
February 15, 2012 19:59
-
-
Save cyberzed/1838562 to your computer and use it in GitHub Desktop.
Rx powered ServiceStack SL Client
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ServiceClient<TRequest, TResponse> | |
where TRequest : class | |
where TResponse : class | |
{ | |
private readonly string _baseUri; | |
private ISubject<TResponse> completionChannel; | |
public ServiceClient(string baseUri = "/api") | |
{ | |
// make sure the base uri is set appropriately | |
if (!baseUri.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) | |
{ | |
var source = Application.Current.Host.Source; | |
var rootUri = source.AbsoluteUri.Substring(0, source.AbsoluteUri.Length - source.AbsolutePath.Length); | |
if (!baseUri.StartsWith("/")) | |
{ | |
baseUri = "/" + baseUri; | |
} | |
baseUri = rootUri + baseUri; | |
} | |
_baseUri = baseUri; | |
// cookies are on by default | |
EnableCookies = true; | |
} | |
public bool EnableCookies { get; set; } | |
public IObservable<TResponse> Send(string uri, string method, TRequest data = null) | |
{ | |
completionChannel = new AsyncSubject<TResponse>(); | |
// set up the web request | |
var webRequest = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(_baseUri + uri)); | |
webRequest.Method = method; | |
// if cookies are enabled, pass them in from the browser | |
if (EnableCookies) | |
{ | |
webRequest.CookieContainer = new CookieContainer(); | |
webRequest.CookieContainer.SetCookies(new Uri(_baseUri), HtmlPage.Document.Cookies); | |
} | |
// set the accept header so our response is in json | |
webRequest.Accept = "application/json"; | |
// if we have data to stream, start streaming. Otherwise we can get the response now. | |
if (data != null) | |
{ | |
webRequest.BeginGetRequestStream(RequestCallback, new DataContainer(webRequest, data)); | |
} | |
else | |
{ | |
webRequest.BeginGetResponse(ResponseCallback, webRequest); | |
} | |
return completionChannel.ObserveOnDispatcher(); | |
} | |
private void RequestCallback(IAsyncResult asyncResult) | |
{ | |
try | |
{ | |
// Get the web request stream | |
var container = (DataContainer)asyncResult.AsyncState; | |
var webRequest = container.WebRequest; | |
var stream = webRequest.EndGetRequestStream(asyncResult); | |
// set the content type to json | |
webRequest.ContentType = "application/json"; | |
// serialize the object to json and write it to the stream | |
//var serializer = new DataContractJsonSerializer(typeof(TRequest)); | |
//serializer.WriteObject(stream, container.Data); | |
//stream.Flush(); | |
//stream.Close(); | |
// If you want to use ServiceStack's serializer, replace the previous code block with this one. | |
using (var writer = new StreamWriter(stream)) | |
{ | |
var serializer = new JsonSerializer<TRequest>(); | |
serializer.SerializeToWriter(container.Data, writer); | |
} | |
// now we can get the response | |
webRequest.BeginGetResponse(ResponseCallback, webRequest); | |
} | |
catch (Exception ex) | |
{ | |
// Raise our own event for the error on the UI thread | |
completionChannel.OnError(ex); | |
} | |
} | |
private void ResponseCallback(IAsyncResult asyncResult) | |
{ | |
try | |
{ | |
// Get the web response | |
var webRequest = (HttpWebRequest)asyncResult.AsyncState; | |
var webResponse = webRequest.EndGetResponse(asyncResult); | |
// Get the web response stream | |
var stream = webResponse.GetResponseStream(); | |
// Deserialize the json data in the response stream | |
//var serializer = new DataContractJsonSerializer(typeof(TResponse)); | |
//var response = (TResponse)serializer.ReadObject(stream); | |
// If you want to use ServiceStack's serializer, replace the previous code block with this one. | |
TResponse response; | |
using (var reader = new StreamReader(stream)) | |
{ | |
var serializer = new JsonSerializer<TResponse>(); | |
response = serializer.DeserializeFromReader(reader); | |
} | |
Deployment.Current.Dispatcher.BeginInvoke(() => | |
{ | |
// if cookies are enabled, pass them back to the browser | |
if (EnableCookies && webRequest.CookieContainer != null) | |
{ | |
var cookieHeader = webRequest.CookieContainer.GetCookieHeader(new Uri(_baseUri)); | |
HtmlPage.Document.Cookies = cookieHeader; | |
} | |
}); | |
//Raise our own event for the response | |
completionChannel.OnNext(response); | |
completionChannel.OnCompleted(); | |
} | |
catch (Exception ex) | |
{ | |
// Raise our own event for the error on the UI thread | |
completionChannel.OnError(ex); | |
} | |
} | |
public IObservable<TResponse> Get(string uri) | |
{ | |
return Send(uri, "GET"); | |
} | |
public IObservable<TResponse> Post(string uri, TRequest data = null) | |
{ | |
return Send(uri, "POST", data); | |
} | |
public IObservable<TResponse> Put(string uri, TRequest data = null) | |
{ | |
return Send(uri, "PUT", data); | |
} | |
public IObservable<TResponse> Patch(string uri, TRequest data = null) | |
{ | |
return Send(uri, "PATCH", data); | |
} | |
public IObservable<TResponse> Delete(string uri, TRequest data = null) | |
{ | |
return Send(uri, "DELETE", data); | |
} | |
private class DataContainer | |
{ | |
public DataContainer(HttpWebRequest webRequest, TRequest data) | |
{ | |
WebRequest = webRequest; | |
Data = data; | |
} | |
public HttpWebRequest WebRequest { get; private set; } | |
public TRequest Data { get; private set; } | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ssClient = new ServiceClient<HelloRequest, HelloResponse>(""); | |
var request = new HelloRequest { Name = "Stefan" }; | |
ssClient.Post("/hello", request).Subscribe(helloResponse => MessageBox.Show(helloResponse.Greeting)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment