Skip to content

Instantly share code, notes, and snippets.

@jgable
Created March 22, 2011 17:49
  • Star 7 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save jgable/881673 to your computer and use it in GitHub Desktop.
A basic JsonService using WebClient and DataContractJsonSerializer for Windows Phone 7, along with an example of how to use it.
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);
});
}
}
@maspan
Copy link

maspan commented Jul 16, 2015

The service is very useful, thanks a lot.

I would like to get the resp.Data and check the JSON response but resp.Data does not give me any output. I had to remove the

MessageBox.Show(resp.Data, "Response", MessageBoxButton.OK);

because it gives me an error of "System.ArgumentNullException"

The only way to read the response from server, was to go to HandleUploadStringComplete and add a debug line.

 private void HandleUploadStringComplete(object sender, UploadStringCompletedEventArgs e)
    {
        CommonHandleResponse(e.Error, e.UserState, () => e.Result);
        Debug.WriteLine("Web service on UploadStringComplete says: " + e.Result);
    }

but what I want to do is from main page check what the login response is based on XML returned
eg.

"login": {
    "result": "ok",
    "reason": "ok",
    "user_registered": 0
},
"user": {
    "current_date": "2015-07-16 09:27:46",
    "user_id": "48449",
}

Could you help me with that? Thanks a a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment