Swami goes Techie

Here i would share my insights on technologies.

Thursday, September 17, 2009

Friendly RESTful urls, using Http Modules

REST follows

As mentioned in my earlier post(RESTful implementation using .Net) i would like to share further lights on RESTful implementation using .net, this time on implementing friendly RESTful urls using HTTP Modules. On my way to this accomplishment, i was initially doing POCs on HTTP handlers to get the job done and if readers could recollect my questions /doubts that i raised in my previous post(URL Rewriting/Redirecting for Web Service(s) – But How?) regarding the same. At last i found that HTTP modules is the perfect candidate for url redirections and not HTTP handlers.

Friendly REST urls

As an example , for a url, (the below shown url is the same RESTful url, that i had implemented in my earlier post(RESTful implementation using .Net) to get employee details).

http://domain.com/employeeprofile.asmx/GetInfo?empid=1

we can make it user friendly as below,

http://domain.com/employeeprofile/GetInfo/1

i am going take this simple scenario and show how such friendly url rewriting can be implemented using HTTP Modules. Once we get the concept, we can go ahead in developing robust url rewriting engines.

HTTP Module

HTTP Module is one of the extensibility feature and advantage provide in .Net Framework. This helps in intercepting and manipulating each of the http requests that comes  from the client to the server application. Now in order to provide meaningful RESTFul urls, i am going to make use of this advantage provided by the HTTP pipeline. Below diagram describes the HTTP pipeline and the components involved in a typical client server architecture involving .net.

clip_image002

In order to tap the incoming request using http module in our application (Web, Web service, etc) following things are to be performed.

Implementation

1. Creating Http Module class :

Add a normal class file to the application which implements  IHttpModule and its members,

System.Web.IHttpModule.Init(System.Web.HttpApplication)  &

System.Web.IHttpModule.Dispose().

The Init method can be made use to perform  initializations that are required and which also holds the handle to the HttpApplication object which  in turn has control over the request, response objects.

Here in the Init method, i am adding a event handler which processes the application’s begin request event.

public void Init(System.Web.HttpApplication app)
        {
            app.BeginRequest += new EventHandler(Rewrite_BeginRequest);

        }

then in my Rewrite_BeginRequest custom method,  i am adding a simple piece of code,which intercepts the incoming request url, checks for the user-friendly format ( these formats are to be predefined and shared to the consumers of the webs service as some manuals / guidelines, so that they get an idea on how to query for a particular data), if valid,  rewrites the url  to the original page with the desired & required parameters as query strings.

Pseudo code of the Rewrite_BeginRequest(object sender, System.EventArgs args) implementation,

1. Typecast the incoming sender object to the http application object in order to get the handle of request, response, context and other asp.net objects.

System.Web.HttpApplication Appl = (System.Web.HttpApplication)sender;

2. Tap the incoming request url, look for the friendly url pattern "/employeeprofile/GetInfo/”, if valid , crop , validate and store the id part which follows the pattern.(the valid employee id number like 1, 10, etc which comes as part of the ur after the pattern -  "/employeeprofile/GetInfo/1 ) .

3. Now, once the id is retrieved, rewrite the url to the original page by using,

Appl.Context.RewritePath("employeeprofile.asmx/GetInfo?empid=1");

That's it, now the coding for the url rewriting is done. as this is a simple demonstration i have hard-code the urls, but when it comes to real-time implementation we can define the friendly url patterns and their respective redirection urls in some configuration file and create  a url redirection module / library /engine which performs the above pseudo logic.

2. Web Config entry:

Once the coding part is over, we need to configure the custom http module in the web config, hence forth ASP.Net engine recognizes the module and invokes it,

<httpModules> 
<add type="RESTFulService.RESTfulHandlerModule,RESTFulService"      name="RESTFulRewriter" />

</httpModules>

the type attribute, takes in classname, assemblyname as input.

the name attribute is any meaningful name.

I hope this post would be a starter point in the future implementation of a robust URL rewriter engine.

Labels: , , , ,

Thursday, September 10, 2009

URL Rewriting/Redirecting for Web Service(s) – But How?

Getting Started:

I am trying out with a simple URL redirection technique; if I am successful in this approach I will go ahead in implementing friendly RESTful urls for my application. But it’s not happening the way I desired though.

Problem Definition:

I am facing problem in URL redirection while using HTTP handler technique;

I have created a VisualStudio2008 web service application.

Added 2 services, Service1.asmx and Service2.asmx.

Scenario 1:

Added an HTTP handler (GenericHandler) class in the same hierarchy. 

Added the below code in ProcessRequest method,

if (context.Request.PhysicalPath.IndexOf("Service1.asmx") > -1)

                    context.RewritePath("~/Service2.asmx");

Registered the Handler in the HTTP handler section of the webconfig, the bold one

<remove verb="*" path="*.asmx"/>

<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>

<add verb="*" type="RESTWS.RESTHandler,RESTWS" path="*.asmx"/>

Now, I run my application by making Service1.asmx as the start page, the process hits my handler code, executes it with out any exception, but at last I see a blank screen in the browser.

For crossing my code I also did the following,

Scenario 2:

Added a Global.asax file in the in the same hierarchy.

Added same code in Application_BeginRequest

if (Context.Request.PhysicalPath.IndexOf("Service1.asmx") > -1)

                Context.RewritePath("~/Service2.asmx");

Commented out the Handler registry part what I added in the webconfig.

Again ran the application, the redirection from Service1.asmx to Service2.asmx happened successfully as expected.

Scenario 3:

When I have both the Global.asax and the http handler enabled, again I get a blank page.

Scenario 4:

I felt that HTTP handler does not support url redirection in the case of asmx(web services), so I tried the same above procedures and scenarios with VisualStudio2008 Web application with 2 aspx pages (Default1.aspx and Default2.aspx) instead of Web service application. But the results were same as the above scenarios.

My Questions:

What is the mistake I am doing in my above scenarios?

How to perform url redirection for web services using Http Handlers?

Looking fwd:

Some help and suggestions extended in this regard will be greatly appreciated.

Labels: , , , ,

Sunday, August 30, 2009

RESTful implementation using .Net

Need REST from SOAP

Yes, we are tried of using SOAP and badly in need of REST;  Till date we would have mostly come across web services being implemented using SOAP (Simple Object Access Protocol) as messaging protocol for exchanging structured information (XML was chosen as the standard message structure) over HTTP (transporting medium). Though it has its own advantages, may get cumbersome due to its verbose XML format by adding soap headers and other meta-datas, thereby making it slower and also failing to utilize the power of HTTP to the fullest.

Lets REST

REST (Representational State Transfer Protocol) on the other hand defines identifiable resources (URIs - uniform Resource Identifiers), and methods for accessing and manipulating the state of those resources (HTTP verbs). Resources are like objects, they clearly differentiate each state very similar as in OOPs where each real-world entity is identified as an object having their own state (method) and attributes (properties).Resources can be identified using a single identifier scheme, typically a URL or URI. Once you have a handle/access to the resource, you can invoke methods (any http verb) and interact with it.

Few HTTP verbs,

  • GET: retrieve resource
  • POST: process resource
  • PUT: update resource representation
  • DELETE: delete resource

REST requests are modeled after the way a web browser (client) sends requests to a web server, typically a request for the REST services mostly goes in through url with query strings or in POST data block.

Typical REST request

A typical REST request for calling a web method GetInfo which takes integer ‘empid’ as the parameter will look similar to

http://domain.com/employeeprofile/GetInfo?empid=1

Each request starts with the hostname

http://domain.com

After the hostname is the service name

/employeeprofile/

Next is the method name followed by a question mark (?), followed by the actual query parameters, which take the form argument=value, where the arguments and values can be URL encoded if required. Multiple parameters are separated by an ampersand (&).

GetInfo?empid=1

Note:  

1. Method name is case sensitive

2. The order of method parameters is irrelevant and names are case insensitive.

3. If a web method takes some complex parameters, for e.g.) like array,

Public void SetNames(String [] empNames)

Then at the client program while calling the method, we pass the values as

http://localhost:3578/Service1.asmx/GetEmpInfo?empNames=Sethu&empNames=Ram&empNames=Kumar.

The REST service is intelligent enough to group up the query string params with name empNames into a string[] of empNames.

REST Implementation

In order make the .Net web service application to work as Restful services,

1. We need to configure web config file to add the required HTTP verbs.

<system.web>

    <webServices>

      <protocols>

        <add name="HttpGet"/>

        <add name="HttpPost"/>

      </protocols>

    </webServices>

</system.web>

2. Then we can go ahead and create normal web methods using c# .Net web service application as we do earlier.

[WebMethod]

public EmployeeList GetEmpInfo(int empid)

Input:

            empid: required integer paramter.

            If  empid = 0, then it will return the details of all the employees of domain(some x company).

            If  empid is any valid id number of the employee it would return his/her corresponding details.

Output schema:

EmployeeList: It’s basically a serialized list of employee object. (NAME and ID)

<Employees>

<Employee>

  <NAME>Anand</NAME>

  <ID>1</ID>

</Employee>

<Employee>

  <NAME>Abhishek</NAME>

  <ID>2</ID>

</Employee>

<Employee>

  <NAME>Jyothi</NAME>

  <ID>3</ID>

</Employee>

<Employee>

  <NAME>Sethuram</NAME>

  <ID>4</ID>

</Employee>

<Employees>

3. When it comes to accessing these web methods, its not require to create a proxy or stub at the consuming client. We can invoke the web methods using simple HttpWebRequest and HttpWebResponse objects and call the required service url along with parameters as below,

< http://localhost:3578/Service1.asmx/GetEmpInfo?empid=4>

string result = string.Empty;

string url = "http://localhost:3578/Service1.asmx/GetEmpInfo?empid=4";

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

request.Method = "GET";

using(HttpWebResponse response = HttpWebResponse)request.GetResponse())

{

using (Stream responseStream = response.GetResponseStream())

                  {

using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8))

                        {

                        XmlDocument xmlDocument = new XmlDocument();

                        xmlDocument.LoadXml(readStream.ReadToEnd());

                        }

                  }

}

Once we get the response output xml schema, we can load it either in XML DOM or parse it through a reader object.

REST Advantages

  • Human readable formats and results.
  • They are stateless.
  • Light weight as purely http.
  • No security issues with firewalls
  • Relative ease and quick to develop.

Companies using REST

  • Yahoo! - All Yahoo API's Web Services uses REST including Flickr etc
  • Google - Google Adsense Search and Google Maps are two good examples for RESTful services implemented by Google
  • Amazon
  • EBay
  • del.ico.us

I am sure this list to going to grow exponentially due to its simplicity to develop and ease of use.

Rest of REST in Rest

I hope I have thrown a bit of light on the RESTful design concepts. (I am sure REST will have a greater impact on the future of the World Wide Web). Here in this post, I have just briefed on the fundamentals of RESTful service, may be I can elaborate on the rest of RESTful design concepts in the rest of my blog posts to follow.

Labels: , ,