Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / IIS

REST at Your Own Risk!

4.53/5 (18 votes)
3 Mar 2014CPOL9 min read 31.2K   446  
REST – Representational State Transfer, implementation

Introduction

I know, the title seems misleading, but with REST – Representational State Transfer, the simplicity comes with risk - if you don’t understand and don't implement REST correctly. REST is not as simple as it seems. The concept seems simple enough but the devils in the details as we will soon see. This post will try to put forth some of the issues, with its implementation and their possible solutions.

Firstly, there is so much written out there on REST that is all a blur... viz.

REST is not a specification, it is a theory. The simplicity and power of the whole concept. REST is CRUD over HTTP and how it is not! GET, POST, PUT, DELETE verbs make up REST. No SOAP, No RPC – development simple and implementation even simpler. The whole debate over WCF REST Services and Web API are not REST, they are RPC over HTTP GET and POST work over HTTP but PUT and DELETE don’t.

Secondly, when you go and start the implementation, there are many issues (server side and client side) which you could encounter.

This post will try to explain REST in the simplest manner, with a very very basic implementation, and try to show some of the problems with its practical implementations and will put forth some ideas to solve those problems.

We will demonstrate the following:

We will create a Generic Handler/IHTTPHandler, which will represent our REST Service. The HTTPHandler will return us a collection of books. We would be able to add, update, delete and query to that collection over HTTP. The REST service will be using Session to store its data.

Note: REST does not encourage Session State management on the server, we are using it just for this demo as an alternative to physical data store. To test our REST Service we will use, a HTTP Client - Postman - REST Client in the Chrome browser. We will show how GET and POST requests work and how and why PUT and DELETE don’t and will show how to fix the issues.

We will not show the following:

We will not explain or discuss REST as a specification/practice in detail.We will not be creating a fancy UI or a client to complicate the matters. We are not using WCF REST Service or ASP.NET Web API as we want to demonstrate the simplicity of the concepts and issues surrounding the implementations.

Note: WCF REST Service or ASP.NET Web API use the HTTPHandler as the root of it all.

The REST service is not connected to any backend or data source and we are not showing data access or that matter Entity Framework!

Implementation

We start by creating a new ASP .NET Empty Web Application and name it RESTService-Demo1.

To this newly created project, we add a new Folder - Data. We add a class Book.cs and a Generic Handler BooksHandler.ashx to the new folder.

Our Books.cs will be as follows:

Image 1

Our Generic Handler BooksHandler.ashx – will look as follows:

Image 2

Some points of interest are highlighted above and detailed below.

The Handler [BooksHandler] implements IHttpHandler, which has a member ProcessRequest(). As we also need access to Session, we have implemented IRequiresSessionState interface. When the Handler is called and ProcessRequest() method is executed, we can access the type of request, the data sent by the client and much more via the context parameter. Based on the RequestType, we call corresponding methods in our REST service.

The GetBooks() method is described below:

GetBooks()

We check if the client has passed in a BookId in the request, if it is not - then we construct the List of Books [5] in a loop and store it in the session. We return the Books list to the client in JSON via the ReturnBooksToClient() method.

If the user is interested in a particular Book, he or she passes its BookId and we select the Book "bookToReturn” and return it to the client.

Our default GET request and its response will look as below. Here we haven’t passed in any BookId and hence been returned all the books in our list.

Image 4

When we pass in the BookId, we get the book in response. Note here that the BookId is passed in as a query string.

Image 5

In our POST request, we pass in a BookId. Our UpdateBook() method, looks for the BookId in our Books collection and updates it by appending “- Updated” to it Name, Authors and Description data members. We then return all the books in the collection as below...

Image 6

In real world application, we would have to pass the data to be updated, from our client. This is just a demo, so we are bending a few rules.

Now let us try to insert a new Book to our collection by passing in the PUT request. Our handler already has all the code to handle the request and update our books collection in its AddBook() member.

As it turns out, we cannot pass a PUT or even a DELETE request to our Handler. We get the following error. "HTTP Error 405.0 - Method Not Allowed".

Image 7

It is very clear from the error that the RequestType also called HTTP Verb or Method: PUT and DELETE we passed in to our handler is not allowed.

Now the million dollar question is: who is not allowing these verbs and why. If that is the case, then how is our REST service aka Generic Handler going to work and how does it work elsewhere?

And the million dollar answer is: Our web application hosted on IIS is not configured to handle PUT and DELETE requests. Typically GET and POST requests are enough for communication over HTTP. In fact, ASP.NET uses POST most exclusively. Postback rings any bell?

PUT and DELETE are in a way considered unsafe. Please note, I don’t want to sound alarmist but, there is solid thought behind not allowing PUT and DELETE. PUT is used for creating and DELETE is used for deleting obviously – Not allowing the user of the application access to these verbs, means the user cannot create or delete anything directly. That is why these two verbs are not allowed by default.

But REST wants to use these verbs! Hence we will make sure our REST service gets what it demands.

Solution to the PUT and DELETE Predicament

Option 1: The configuration...

Following are the configurations for allowing PUT and DELETE operation in our application.

For allowing CRUD [PUT, GET, POST, and DELETE] operations over HTTP for our Handler aka REST Service, we need the following settings:

The application needs to be hosted on an IIS Web Server.

Need the Application Pool with:

.NET Version Framework: 4.0

Pipeline Mode: Integrated

Image 8

Note: I am currently hosing with .NET runtime 4.0, but configurations will almost be the same baring the runtime for older .NET versions.

The required settings in the web.config are:

Image 9

Important setting are highlighted. More details can be found here.

After the changes to our application on IIS, the PUT and DELETE start working.

Image 10

Option 2: The code...

There might be cases (some listed below), where we are not able to configure our applications with the above solution.

  • Our System or Web Server Administrator is not allowing our application to have PUT or DELETE permissions.
  • We need to maintain the CRUD implementation in your service (GetBooks(), AddBook(), DeleteBook()), but give your clients a formal alternative for making PUT or DELETE requests.
Hence, a code solution to the problem. The technique is formally called as Verb Tunneling - here we pass our PUT or DELETE requests bundled inside a POST request with the header "X-HTTP-Method-Override".

We won’t need any special configurations either on the IIS side or in our web.config file. We will use the code from our previous example as our base and build on top of it. The code will be available as RESTService-Demo2.

We begin, by removing the handler configuration we added to our web.config file, in the above example. Note: We can maintain the original configuration in the web.config, if we wish to support both, the direct PUT and DELETE requests as well as the Verb Tunneling solution.

If updated, our web.config file will be very simple and will look like the following:

XML
<?xml version="1.0"?> 
<configuration> 
    <system.web>
        <compilation targetframework="4.5" debug="true">
            <httpruntime targetframework="4.5">
            </httpruntime>
        </compilation>
    </system.web>
</configuration>  

Next we add a Global Application Class – Global.asax file to the root of the project. To the file, we add the following code to its Application_BeginRequest event.

C#
protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (Request.RequestType.ToUpper() == "POST")
    {
        if (Request.Headers.AllKeys.Contains("X-HTTP-Method-Override", StringComparer.OrdinalIgnoreCase))
        {
        string overrideMethod = Request.Headers.Get("X-HTTP-Method-Override");

        if (overrideMethod.Contains("PUT") || overrideMethod.Contains("DELETE"))
            Request.RequestType = overrideMethod;
        }
    }
} 

The Application_BeginRequest() event is executed on each request - our application receives. In the event, we check if the Request is of type “POST” and the Request Header contains an entry for "X-HTTP-Method-Override". If it does, we convert the Request Type from POST to the value passed in the "X-HTTP-Method-Override" header.

We will continue from the earlier example and test our code with Postman - REST Client. Our GET and POST request/responses will remain the same, so we will focus on the PUT and DELETE requests.

Our updated request for DELETE will look as follows:

Image 11

Here, we are missing Book # 1 in the response, proving that our DELETE has worked.

Our updated request for PUT(Insert) will look as follows.

Image 12

Here, we have gained Book # 6 in our response, proving PUT also works.

These requests will reach our Application_BeginRequest() event in our Application File(Global.asax) and will be transformed into respective PUT and DELETE request.

Here, our application, IIS configuration or our system administrators are not troubled as all the request come in as either GET or POST, which are considered SAFE.

Our clients, who are unable to make direct PUT or DELETE calls need to pass in their requests through the Request Header “X-HTTP-Method-Override”.

For those clients who can make a PUT or DELETE request, there is no change, provided we have maintained our previous web.config file from our previous option.

This concludes our demo showing CRUD over HTTP using Generic Handler used as a REST Service. Below are a few very important points which need to he considered before opting for the techniques described.

  1. The demo is only for demonstration purposes, in real life application there would be more to our REST Service like Authentication, Authorization and Validations.
  2. In most cases, your System Administrator won’t allow you to have DELETE and PUT permissions for your applications. For instance, in our case, we are firing PUT and DELETE requests on our application at will! In a real application, this would be unfathomable. This is not to say we cannot or should not do this, but all the PROS and CONS need to be considered.
  3. There can be firewalls which would block PUT and DELETE requests.
  4. The clients need to be told, to send “X-HTTP-Method-Override” in the Request Header if the Verb Tunneling option is used for PUT and DELETE.

I hope now it would be clear why I said “REST at your own risk!”

I will try to write something next time which will have a client for our tiny REST service. Till then..

History

  • March 4 2014: Original post
  • May 01 2014: Added the "code option" for allowing PUT and DELETE HTTP verbs

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)