This is an idea I've been playing with... use at your own risk, the code is in my "Sandbox" folder ;)
I think I want to move away from using reflection to determine which method to run, it might be faster to register a delegate in a dictionary using the HttpVerb as a key. Anyway, this code is provided with no warranty, blah, blah, blah...
Verbs to use with REST Service
public enum HttpVerb
{
GET, POST, PUT, DELETE
}
Attribute to mark methods on your service
[AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=false)]
public class RestMethodAttribute: Attribute
{
private HttpVerb _verb;
public RestMethodAttribute(HttpVerb verb)
{
_verb = verb;
}
public HttpVerb Verb
{
get { return _verb; }
}
}
Base class for a Rest Service
public class RestService: IHttpHandler
{
private readonly bool _isReusable = true;
protected HttpContext _context;
private IDictionary<HttpVerb, MethodInfo> _methods;
public void ProcessRequest(HttpContext context)
{
_context = context;
HttpVerb verb = (HttpVerb)Enum.Parse(typeof (HttpVerb), context.Request.HttpMethod);
MethodInfo method = Methods[verb];
method.Invoke(this, null);
}
private IDictionary<HttpVerb, MethodInfo> Methods
{
get
{
if(_methods == null)
{
_methods = new Dictionary<HttpVerb, MethodInfo>();
BuildMethodsMap();
}
return _methods;
}
}
private void BuildMethodsMap()
{
Type serviceType = this.GetType();
MethodInfo[] methods = serviceType.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public);
foreach (MethodInfo info in methods)
{
RestMethodAttribute[] attribs =
info.GetCustomAttributes(typeof(RestMethodAttribute), false) as RestMethodAttribute[];
if(attribs == null || attribs.Length == 0)
continue;
HttpVerb verb = attribs[0].Verb;
Methods.Add(verb, info);
}
}
public bool IsReusable
{
get { return _isReusable; }
}
}
Sample REST Service
public class MyRestService: RestService
{
[RestMethod(HttpVerb.GET)]
public void HelloWorld()
{
_context.Current.Response.Write("Hello World");
_context.Current.Response.End();
}
}