Skip to content

Instantly share code, notes, and snippets.

@PaulCampbell
Created March 25, 2011 12:53
Show Gist options
  • Save PaulCampbell/886799 to your computer and use it in GitHub Desktop.
Save PaulCampbell/886799 to your computer and use it in GitHub Desktop.
Generic repository style service for REST services
public interface IJsonService<T>
{
// Methods
void Delete(T entity);
IList<T> FindAll(IDictionary<string, object> propertyValuePairs, int pageNo, int resultsPerPage, string sortBy, string sortDirection);
T Get(int id);
IList<T> Get(List<int> IDs);
IList<T> GetAll(int pageNo, int resultsPerPage, string sortBy, string sortDirection, string segment);
RestResult Save(T entity);
RestResult Update(T entity);
IList<T> GetRelatedObjectsForEntity(string entityType, int entityId);
}
public interface IRestResource
{
int ID { get; set; }
}
public class JsonService<T> : IJsonService<T> where T : IRestResource
{
private readonly string _serviceEndPoint = System.Configuration.ConfigurationManager.AppSettings["RestURL"];
public void Delete(T entity)
{
throw new NotImplementedException();
}
/// <summary>
/// Searches resources for instances that "start with" values in property keys
/// </summary>
/// <param name="propertyValuePairs">Dictionary of search keys / values - matches when "key" column starts with "value"</param>
/// <param name="pageNo">page number </param>
/// <param name="resultsPerPage">how many results per page</param>
/// <param name="sortBy">column to sort by</param>
/// <param name="sortDirection">direction (ASC || DESC)</param>
/// <returns></returns>
public IList<T> FindAll(IDictionary<string, object> propertyValuePairs, int pageNo, int resultsPerPage,
string sortBy, string sortDirection)
{
// Do we need to match on beginswith || equals || ends with???
var matchtype = "beginswith";
var searchString = "filter=";
foreach (var p in propertyValuePairs)
{
searchString = String.Format("{0}{1}.{2}.{3}", searchString, p.Key,matchtype, p.Value);
}
var uri = String.Format("{0}/{5}/?offset={1}&limit={2}&sorttype={3}&sortby={4}&{6}",
_serviceEndPoint, pageNo, resultsPerPage, sortDirection, sortBy, typeof (T).Name,
searchString);
string resp = GetJson(uri, HttpMethod.GET.ToString());
var o = JObject.Parse(resp);
var returnResources = o.SelectToken(typeof(T).Name + "s");
var models = GetModels(returnResources);
return models;
}
/// <summary>
/// Return the full resource
/// </summary>
/// <param name="id">Id of the resource</param>
/// <returns></returns>
public T Get(int id)
{
// Grab the json feed from the service...
var uri = String.Format("{0}/{1}/{2}", _serviceEndPoint, typeof (T).Name, id);
var o = JObject.Parse(GetJson(uri, HttpMethod.GET.ToString()));
var returnResource = o.SelectToken(typeof(T).Name + "s");
// deserialise it for the view
var models = GetModels(returnResource);
return models[0];
}
public IList<T> Get(List<int> IDs)
{
var listOfIds = "";
foreach(var i in IDs)
{
listOfIds += i.ToString() + ",";
}
var uri = String.Format("{0}/{1}/{2}", _serviceEndPoint, typeof(T).Name, listOfIds);
var o = JObject.Parse(GetJson(uri, HttpMethod.GET.ToString()));
var returnResources = o.SelectToken(typeof(T).Name + "s");
var models = GetModels(returnResources);
return models;
}
/// <summary>
/// Get a list of resources
/// </summary>
/// <param name="pageNo">page number </param>
/// <param name="resultsPerPage">how many results per page</param>
/// <param name="sortBy">column to sort by</param>
/// <param name="sortDirection">direction (ASC || DESC)</param>
/// /// <param name="segment">name of segmented data (e.g. userwhohavenotloggedin)</param>
/// <returns></returns>
public IList<T> GetAll(int pageNo, int resultsPerPage, string sortBy, string sortDirection, string segment)
{
var uri = String.Format("{0}/{5}/?offset={1}&limit={2}&sorttype={3}&sortby={4}&segment={6}", _serviceEndPoint, pageNo,
resultsPerPage, sortDirection, sortBy, typeof(T).Name, segment);
var o = JObject.Parse(GetJson(uri, HttpMethod.GET.ToString()));
var returnResources = o.SelectToken(typeof (T).Name + "s");
var models = GetModels(returnResources);
return models;
}
/// <summary>
/// Save a new resource
/// </summary>
/// <param name="entity">the new resource</param>
/// <returns>rest call result object</returns>
public RestResult Save(T entity)
{
var restResult = PushJson(String.Format("{0}/{1}/", _serviceEndPoint, typeof (T).Name),
HttpMethod.POST.ToString(), entity);
return restResult;
}
/// <summary>
/// Update a resource
/// </summary>
/// <param name="entity">the resource to persist</param>
/// <returns>rest call result object</returns>
public RestResult Update(T entity)
{
var restResult = PushJson(String.Format("{0}/{1}/{2}", _serviceEndPoint, typeof (T).Name, entity.ID),
HttpMethod.PUT.ToString(), entity);
return restResult;
}
/// <summary>
/// Method for retrieving an objects related resources.
/// for example: UserAccount/1/UserGroups
/// </summary>
/// <param name="entityType">The name of the base entity - UserAccounts in the above example</param>
/// <param name="entityId">The ID of the base entity</param>
/// <returns>A list of objects related to the base entity</returns>
public IList<T> GetRelatedObjectsForEntity(string entityType, int entityId)
{
var uri = String.Format("{0}/{1}/{2}/{3}s", _serviceEndPoint, entityType, entityId.ToString(), typeof(T).Name);
var o = JObject.Parse(GetJson(uri, HttpMethod.GET.ToString()));
var returnResources = o.SelectToken(typeof(T).Name + "s");
var models = GetModels(returnResources);
return models;
}
/// <summary>
/// POST or PUT an object to the REST service
/// </summary>
/// <param name="uri">The URI of the resource</param>
/// <param name="httpMethod"></param>
/// <param name="entity"></param>
/// <returns></returns>
private RestResult PushJson(string uri, string httpMethod, T entity)
{
string json = Newtonsoft.Json.JsonConvert.SerializeObject(entity);
byte[] arr = System.Text.Encoding.UTF8.GetBytes(json);
var webRequest = GetWebRequest(String.Format("{0}/{1}/{2}", _serviceEndPoint, typeof (T).Name, entity.ID));
webRequest.Method = httpMethod;
webRequest.ContentType = "application/json";
webRequest.ContentLength = arr.Length;
Stream dataStream = webRequest.GetRequestStream();
dataStream.Write(arr, 0, arr.Length);
dataStream.Close();
try
{
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
// Service responses:
string returnString = response.StatusCode.ToString();
var jsonResult = new StreamReader(response.GetResponseStream()).ReadToEnd();
var o = JArray.Parse(jsonResult);
var restResult =
Newtonsoft.Json.JsonConvert.DeserializeObject<RestResult>(
o[0].ToString());
foreach (JProperty j in o[0].SelectToken("Fields"))
{
var f = new Field();
f.FieldName = j.Name;
f.Message = j.Value["Message"].ToString();
f.Status = j.Value["Status"].ToString();
restResult.Forms.Add(f);
}
return restResult;
}
catch (Exception e)
{
// Network down... What do we want to do?
throw;
}
}
private string GetJson(string uri, string httpMethod)
{
var webRequest = GetWebRequest(uri);
webRequest.Method = httpMethod;
webRequest.ContentType = "application/json";
try
{
var response = (HttpWebResponse)webRequest.GetResponse();
var jsonResponse = string.Empty;
using (var sr = new StreamReader(response.GetResponseStream()))
{
jsonResponse = sr.ReadToEnd();
}
return jsonResponse;
}
catch (Exception e)
{
// Network down... What do we want to do?
throw;
}
}
private static HttpWebRequest GetWebRequest(string formattedUri)
{
var serviceUri = new Uri(formattedUri, UriKind.Absolute);
return (HttpWebRequest) System.Net.WebRequest.Create(serviceUri);
}
private List<T> GetModels(JToken returnResources)
{
List<T> models;
if (returnResources == null || returnResources.Type == JTokenType.Null)
{
// There were no results in the list...
return new List<T>();
}
if (returnResources.Type.ToString() == "Array")
{
models = Newtonsoft.Json.JsonConvert.DeserializeObject<List<T>>(returnResources.ToString());
}
else
{
// if there is only 1 result, the service does not return an array... we must serialise accordingly.
models = new List<T>();
models.Add(Newtonsoft.Json.JsonConvert.DeserializeObject<T>(returnResources.ToString()));
}
return models;
}
}
public enum HttpMethod
{
GET = 1,
POST = 2,
PUT = 3,
DELETE = 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment