Creating Rest Services in asp.net with httphandler

Rest Services with Custom handler -

In .Net Microsoft provide the rest architecture building api in WCF application that manage request and response over webHttpBinding protocol.

As I discuss in my previous post (Rest service tutorial with WCF service) that we can also make our own rest architecture manually through http handler to creating the rest service that would be more efficient and simple to understand what going on inside the rest.


ASP.NET web services are in fact a type of HttpHandler that provide an XML based communication infrastructure based on W3C standards (SOAP/WSDL). This means that non .NET clients can interoperate with ASP.NET web services. In your case where you're making a very simple single ajax request to return a simple result, ASP.NET/XML web services may be overkill.

It may be more beneficial/efficient to implement a simple custom HttpHandler rather than invoking all of the plumbing and overhead associated with ASP.NET web services. With a custom HttpHandler you can just send the parameter you need and return exactly the result you want to see without any of the supporting SOAP xml that would be created when using XML web services.

Bellow is the custom handler (We can also use .ashx file but there is no support of virtual path or virtual extension as custom handler provide)
  • Add a .cs class named restHandler inherit IHttpHandler 
  • Implement the all IHttpHandler method (IsReusable, ProcessRequest)

<system.web>
 <httpHandlers>
   <add verb="*" path="Services.fck" type="restHandler"/>
 </httpHandlers>


If you are hosting your application in IIS 7 then you have to do some additional setting in IIS 7 to be register httphandler in IIS 7 take a look at this link below.

Below is the handler part of the entire code that makes a rest service that is for http GET,POST method and call through 3 lightwaighted communication protocall i.e.
  • Json 
  • Xml 
  • Plain Text 


public class restHandler : IHttpHandler
{
 public htmHandler(){}
 public bool IsReusable
 { get { return false; }}

 public void ProcessRequest(HttpContext context)
 {

  HttpRequest Request = context.Request;
  HttpResponse Response = context.Response;

  if (Request.RequestType == "GET")
  {
   
    //RawUrl=http://localhost/Services.fck/?Vivek/Gupta
    string RawUrl = Request.RawUrl;
    string splitter = "/?";
    string SubRawUrl = RawUrl.Substring(RawUrl.IndexOf(splitter) + splitter.Length);

    string[] Parameters = SubRawUrl.Split('/');
if (Parameters.Length >= 2)
{
    string name = Parameters[0];
    string surname = Parameters[1];
    string res = string.Format("Welcome {0} {1}", name, surname);
    JavaScriptSerializer jc = new JavaScriptSerializer();
    StringBuilder sb=new StringBuilder ();
    jc.Serialize(res, sb);
    Response.Write(sb.ToString());
    Response.ContentType = "application/json";
}
  }
  else if (Request.RequestType == "POST")
  {

    if (Request.ContentType.Contains("text/xml"))
    {
        Request.InputStream.Seek(0, SeekOrigin.Begin);
        XmlDocument xm = new XmlDocument();
        xm.Load(Request.InputStream);

        output.name = xm.DocumentElement["name"].InnerText;
        output.surname = xm.DocumentElement["surname"].InnerText;

        XmlSerializer xr = new XmlSerializer(typeof(output));
        MemoryStream mr = new MemoryStream();
        xr.Serialize(mr, new output());
        byte[] OutXmlByte = mr.ToArray();

        Response.OutputStream.Write(OutXmlByte, 0, OutXmlByte.Length);
        Response.ContentType = "text/xml";
    }
    else if (Request.ContentType.Contains("application/json"))
    {
        string data = Encoding.UTF8.GetString(Request.BinaryRead(Request.TotalBytes));
        JavaScriptSerializer jc = new JavaScriptSerializer();
        Dictionary<string, string> keyValue = jc.Deserialize<Dictionary<string, string>>(data);

        output.name = keyValue["name"];
        output.surname = keyValue["surname"];

        Response.Write(jc.Serialize(new output()));
        Response.ContentType = "application/json";
    }
    else if (Request.ContentType.Contains("text/plain"))
    {
        string data = Encoding.UTF8.GetString(Request.BinaryRead(Request.TotalBytes));
        string[] keyValue = data.Split(',');

        output.name = keyValue[0];
        output.surname = keyValue[1];

        Response.Write(new output().result);
        Response.ContentType = "text/plain";
    }
  }
 }
}


public class output
{
    public output()
    {
        result = "Welcome " + name + " " + surname;
    }
   
    public string result;
   
    [NonSerialized]
    public static string name ;
    [NonSerialized]
    public static string surname;
   
}


Calling form Http GET Method -



function CallGetJSON() {
     $.getJSON("Services.fck/?Vivek/Gupta",
     function(data) {
         alert(data);
     });
}

Direct From Url -

http://localhost:51096/VivekDemo/Services.fck/?Vivek/Gupta

Calling from Http POST Method -

1. From Json


function CallPostJSON() {
 data = "{name:'Vivek',surname:'Gupta'}";
 $.ajax({
    type: "POST",
    url: "Services.fck",
    data: data,
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(response) {
        alert(response.result);
    },
    error: function(xhr, ajaxOptions, thrownError) {
        alert(xhr.status + ' ' + ajaxOptions + ' ' + thrownError);
    }
 });
}


2.  From XML :


function CallPostXML() {
 data = "<?xml version='1.0'?><root> ";
 data += "<name>Vivek</name><name>vinay</name><surname>Gupta</surname>";
 data += "</root>";
 $.ajax({
     type: "POST",
     url: "Services.fck",
     data: data,
     contentType: "text/xml; charset=utf-8",
     dataType: "xml",
     success: function(response) {
         alert($(response).find("result").text());
     },
     error: function(xhr, ajaxOptions, thrownError) {
         alert(xhr.status + ' ' + ajaxOptions + ' ' + thrownError);
     }
 });
}


3. From Plain Text


function CallPostText() {
 data = "Vivek,Gupta";
 $.ajax({
    type: "POST",
    url: "Services.fck",
    data: data,
    contentType: "text/plain; charset=utf-8",
    dataType: "text",
    success: function(response) {
        alert(response);
    },
    error: function(xhr, ajaxOptions, thrownError) {
        alert(xhr.status + ' ' + ajaxOptions + ' ' + thrownError);
    }
 });
}


Points -
$.ajax function :

ContentType Property use by server to match the content formate only (we have to manualy parse content as content type value it is just an variable to match)

ContentType Property used by browser to display the content as its formate not to parse (explicitly)

DataType Property of $.ajax used by jquery, in which format jquery parse the response and return parsed result (response always come as a text sequence of character)


<asp:Button runat="server" ID="btnGet" Text="Call Get Json" OnClientClick="CallGetJSON(); return false;" />
<asp:Button runat="server" ID="btnJson" Text="Call Post Json" OnClientClick="CallPostJSON(); return false;" />
<asp:Button runat="server" ID="btnXml" Text="Call Post Xml" OnClientClick="CallPostXML(); return false;" />
<asp:Button runat="server" ID="btnText" Text="Call Post Text" OnClientClick="CallPostText(); return false;" />
 

Calling Form Server Side (C# Code) :

Use WebClient or WebResponse, WebRequest to Consume the httpHandler Rest service from server side code.

Recent Article