Skip to content

Instantly share code, notes, and snippets.

@SoundLogic
Forked from jgable/JsonService.cs
Created April 1, 2011 16:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SoundLogic/898430 to your computer and use it in GitHub Desktop.
Save SoundLogic/898430 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text;
/// <summary>
/// Strongly typed GET and POST utility enum.
/// </summary>
public enum HTTPMethod
{
GET,
POST
}
/// <summary>
/// Helpers for handling Json Data.
/// </summary>
public static class JsonHelper
{
/// <summary>
/// Deserializes the specified json string, or returns null if it cannot.
/// </summary>
public static T Deserialize<T>(string jsonString)
{
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
T val;
try
{
val = (T)serializer.ReadObject(ms);
}
catch
{
val = default(T);
}
return val;
}
}
}
/// <summary>
/// A basic json service using WebClient.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
public class JsonService<TResult>
{
private WebClient client;
// Holder for our callbacks to pass as state object.
private class Callbacks
{
public Action<TResult> Result { get; set; }
public Action<Exception> Error { get; set; }
}
public JsonService()
{ }
/// <summary>
/// Starts a GET service call to the specified URL.
/// </summary>
protected void StartServiceCall(string uri, Action<TResult> onResult, Action<Exception> onError)
{
StartServiceCall(uri, HTTPMethod.GET, null, onResult, onError);
}
/// <summary>
/// Starts a service call to the specified URL using the specified method and postData.
/// </summary>
protected void StartServiceCall(string uri, HTTPMethod method, string postData, Action<TResult> onResult, Action<Exception> onError)
{
if(client != null)
{
// Remove our previous handlers to prevent mem leaks.
client.DownloadStringCompleted -= HandleDownloadStringComplete;
client.UploadStringCompleted -= HandleUploadStringComplete;
}
client = new WebClient();
client.DownloadStringCompleted += HandleDownloadStringComplete;
client.UploadStringCompleted += HandleUploadStringComplete;
var callbacks = new Callbacks() { Result = onResult, Error = onError };
if (method == HTTPMethod.GET)
client.DownloadStringAsync(new Uri(uri), callbacks);
else
{
client.Headers["Content-Type"] = "application/x-www-form-urlencoded";
client.UploadStringAsync(new Uri(uri), "POST", postData, callbacks);
}
}
/// <summary>
/// Handles the download string complete event of the web client.
/// </summary>
private void HandleDownloadStringComplete(object sender, DownloadStringCompletedEventArgs e)
{
CommonHandleResponse(e.Error, e.UserState, () => e.Result);
}
/// <summary>
/// Handles the upload string complete event of the web client.
/// </summary>
private void HandleUploadStringComplete(object sender, UploadStringCompletedEventArgs e)
{
CommonHandleResponse(e.Error, e.UserState, () => e.Result);
}
/// <summary>
/// Common response handling logic for both download and upload string
/// </summary>
private void CommonHandleResponse(Exception error, object state, Func<string> getResult)
{
// We need our callbacks or everything else is not needed.
var callbacks = state as Callbacks;
if (callbacks == null)
return;
// Handle an error by calling the appropriate callback.
if (error != null)
{
if (callbacks.Error != null)
callbacks.Error(error);
return;
}
// No point in deserializing if we don't have a result callback.
if (callbacks.Result == null || getResult == null)
return;
var result = default(TResult);
try
{
result = JsonHelper.Deserialize<TResult>(getResult());
}
catch (Exception ex)
{
if (callbacks.Error != null)
callbacks.Error(ex);
}
if (callbacks.Result != null)
callbacks.Result(result);
}
}
using System;
using System.Windows;
using Microsoft.Phone.Controls;
public class TestResponse
{
public bool Success { get; set; }
public string Data { get; set; }
}
public class TestService : JsonService<TestResponse>
{
public void StartService(Action<TestResponse> onResp, Action<Exception> onError)
{
StartServiceCall("http://localhost:59527/Person", onResp, onError);
}
}
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
(new TestService()).StartService(
resp =>
{
MessageBox.Show(resp.Data, "Response", MessageBoxButton.OK);
},
err =>
{
MessageBox.Show(err.Message, "Error", MessageBoxButton.OK);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment