using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
using System.IO;
public abstract class CompactRESTHandler<T> : IHttpHandler where T : new()
{
public CompactRESTHandler()
{
}
public bool IsReusable
{
get { return false; }
}
//REF: http://goo.gl/Uk1go
protected static bool IsNullOrEmpty(T item)
{
return EqualityComparer<T>.Default.Equals(item, default(T));
}
public void ProcessRequest(HttpContext context)
{
var args = new Dictionary<string, string>();
JavaScriptSerializer jss = new JavaScriptSerializer();
foreach (var key in context.Items.Keys)
args.Add(key.ToString(), Convert.ToString(context.Items[key]));
//傳回JSON內容的共用方法
Action<object, int> dumpDataJsonWithStatusCode = (data, statusCode) =>
{
if (statusCode > 0)
context.Response.StatusCode = statusCode;
context.Response.ContentType = "application/json; charset=utf-8";
context.Response.Write(jss.Serialize(data));
};
Action<object> dumpDataJson = (data) => { dumpDataJsonWithStatusCode(data, 0); };
//傳回特定Status Code的共用方法
Action<int, string> returnHttpStatus = (statusCode, content) =>
{
context.Response.StatusCode = statusCode;
if (!string.IsNullOrEmpty(content))
context.Response.Write(content);
};
//由HttpMethod及參數決定呼叫何種方法
string httpMethod = context.Request.HttpMethod;
//除了GET以外,POST/PUT/DELETE時,Request的本文內容應為資料物件JSON
//在此將其反序列化回.NET端的物件
T item = default(T);
if (httpMethod != "GET")
{
//檢查ContentType必須為application/json,確保Client端明確知道要傳JSON
if (!context.Request.ContentType.StartsWith("application/json"))
throw new ArgumentException("ConentType is not application/json!");
try
{
//理論上還要依ContentType的charset決定Encoding,在此偷懶省略
using (StreamReader sr = new StreamReader(context.Request.InputStream))
{
string jsonString = sr.ReadToEnd();
item = (T)jss.Deserialize<T>(jsonString);
}
}
catch (Exception ex)
{
throw new ArgumentException("Failed to parse JSON string");
}
}
try
{
switch (httpMethod)
{
case "GET": //GetList及GetItem由是否提供Id來區分
if (args.ContainsKey("id"))
{
item = GetItem(args);
if (IsNullOrEmpty(item))
returnHttpStatus(404, "Not Found!");
else
dumpDataJson(item);
}
else
dumpDataJson(GetList(args));
break;
case "POST":
//傳回HTTP 201 Created
dumpDataJsonWithStatusCode(CreateItem(item), 201);
//加上Response Header - Location
context.Response.AddHeader("Location",
GetCreateLocationHeader(item));
break;
case "PUT":
UpdateItem(item);
break;
case "DELETE":
DeleteItem(item);
break;
}
}
catch (Exception ex)
{
dumpDataJsonWithStatusCode(ex.Message, 500);
}
context.Response.End();
}
//查詢取得物件集合
public abstract List<T> GetList(Dictionary<string, string> args);
//取得特定資料物件
public abstract T GetItem(Dictionary<string, string> args);
//新增資料(需回傳新增成功的資料物件)
public abstract T CreateItem(T item);
//傳回新增資料後的Location Response Header
public abstract string GetCreateLocationHeader(T item);
//更新資料
public abstract void UpdateItem(T item);
//刪除資料
public abstract void DeleteItem(T item);
}