Thursday, October 9, 2008

HTTP GET/POST to the same URL

Recently I worked on a project, in which the user will send a POST or GET request to the same URL. We need to follow few steps to implement this functionality.

The IHttpHandler (System.Web) interface comes to picture in this case. This interface is used to define the contract that ASP.NET implements to synchronously process HTTP Web requests using custom HTTP handlers. This interface has two functions - ProcessRequest() and IsReusable() - which needs to be implemented. The ProcessRequest() receives an HttpContext object and this can be used for further processing.

Sample code for an IHttpHandler implementation is given below. First, a web application is created with name XyzDataCollector. Class DataCollector is added to this project.

public class DataCollector : IHttpHandler
{
   public void ProcessRequest(System.Web.HttpContext context)
    {
        HttpResponse objResponse = context.Response;

        switch (context.Request.HttpMethod)
        {
            case "GET":
                objResponse.Write(context.Request.QueryString["assignmentID"]);
                break;

            case "POST":
                context.Response.Write(context.Request["assignmentID"]);
                break;

            default:
                break;
        }
    }

    public bool IsReusable
    {
        get
        {
            return true;
        }
    }
}

The switch statement in the ProcessRequest() is where the processing takes place. We can distinguish between the GET & POST requests here, as shown. Code is written here for handling these requests (in this example, it just returns the passed value).

Now, the most important step. We need to add the HTTP handler information to the Web.config file (add one if it does not exist in the current project). Under the system.web section, we need to add the httpHandlers details.

<httpHandlers>
   <add verb="*" path="GetAssignment.Assign" type="XyzDataCollector.DataCollector"/>
</httpHandlers>

Few points to be noted here. First, the very '*' indicates that it can accept all requests such as GET, POST etc. Instead of '*', it is possible to specify a combination of these values. The path attribute represents the URL path that will be used to access this and the type identifies the class that will process the request. In this case, I am using a different extension - .Assign - instead of standard type such as .aspx. So, it is necessary to define an extension mapping in IIS, for handling this type of request. For this, open IIS and drill down to the XyzDataCollector virtual directory. Right-click on the directory and select Properties. Then click the Configuration button to show the file types and their mappings. Create a new application mapping by clicking the Add button. If a standard extension such as .aspx is used (which is already defined), these steps are not necessary.

ApplicationConfig

AddISAPIExtension

Once this step is completed, IIS will know how to handle the new extension. One point; we need to select the executable as aspnet_isapi.dll (of the current .NET Framework).

Now, to send a GET or POST request to this URL (from a thick client or thin client application), we can use the following functions.

public void DoGET()
{
    string url = "http://localhost/XyzDataCollector/GetAssignment.Assign?assignmentID=10000";

    // Create the web request  
    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

    // Get response  
    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
    {
        // Get the response stream  
        StreamReader reader = new StreamReader(response.GetResponseStream());

        // Get the response  
        string response = reader.ReadToEnd();

        //
        // Add code for processing the response
        //
    }
}

public void DoPOST()
{
    string url = "http://localhost/XyzDataCollector/GetAssignment.Assign";

    Uri address = new Uri(url);

   // Create the web request  
    HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;

    // Set type to POST  
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";

    StringBuilder data = new StringBuilder();
    data.Append("assignmentID=" + HttpUtility.UrlEncode("10000"));

    // Create a byte array of the data we want to send  
    byte[] byteData = UTF8Encoding.UTF8.GetBytes(data.ToString());

    // Set the content length in the request headers  
    request.ContentLength = byteData.Length;

    // Write data  
    using (Stream postStream = request.GetRequestStream())
    {
        postStream.Write(byteData, 0, byteData.Length);
    }

    // Get response  
    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
    {
        // Get the response stream  
        using (StreamReader reader = new StreamReader(response.GetResponseStream()))
        {
            string response = reader.ReadToEnd();

            //
            // Add code for processing the response
            //
        }
    }  
}

No comments: