Redirect and POST in ASP.NET

Original Post: http://www.codeproject.com/Articles/37539/Redirect-and-POST-in-ASP-NET

Introduction

Recently, I faced a situation where I have an application on which I needed to communicate with a third party payment application, where in some point, I will have to send information to that third party application using POST and not GET.

Background

Well, at first, that sounded easy, but that wasn’t the case at all. I worked on this heavily, Googled intensively, tried hard with no good solution to satisfy my desire. Let’s first see what our options are for submitting data (POST or GET) to a destination URL:

  1. Response.Redirect: This method is widely used and common, but it will only use the GET method in ASP.NET, and there is no way to do a POST using it.
  2. Server.Transfer: This method does a POST not GET, but … unfortunately, it will only work when the source and destination are in the same application; therefore, if you are sending a request to a third party application, this will not work … too bad :S
  3. Using HttpWebRequest: This is another method where you are creating the whole request from scratch, you specify the content, its type, write the data in a concatenated form of “&”, then convert to bytes and submit the request by calling the GetResponse() method … does it do a POST? Yes it does !!! Does it make a redirection to the destination UrRL? No, it doesn’t !!! Even so, you will render the response on the browser for the user and the user will see the destination page perfectly, but any action on this rendered page will end with tears since you are still referring to the same origin of the request … which is your application … so any postbacks on that page will end up displaying 404 .. Page Not Found. (Why? Remember that default postback behaviour is always to the page itself … that’s why Wink | ;) .)
  4. Using a WebClient: This method is my favourite of the listed ones … because it’s easy … create a WebClient object, give it the destination URL, call the UploadValues method which takes a name-value collection (in which all of your POST data is available), render the response, and everything is POSTed perfectly to the destination URL; but like the previous option, you are still in the same place, which is your application … so any postbacks on that page will end up displaying 404 … Page not Found.
  5. HTML Submit button with POST form: Well, this is the standard way of sending POST data to any URL, whether it is in your application or in a third party application, but this will restrict you to have a Submit button, e.g., <input type="submit"/>, and that one will not, of course, do any server side event for you!!! And in one way or another, you are forced to press that button at some point … no other way … too bad :S

Note: if you have other methods .. keep it … Wink | ;) I’ve had enough with what I have seen!

Now, let’s imagine that I have a Response.Redirect method to which I give a collection of data and I tell it to do a POST method instead of a GET method … wouldn’t that be wonderful? I think that will be great … really a simple wish! Smile | :)

Now, that’s the whole point, to have a method to which I give a collection of data to be submitted to the destination URL and then all data is POSTed with redirection.

Using the code

I am attaching a file with this article, which has a class called HttpHelper. This class has only two methods: a private method PreparePOSTForm and a public method RedirectAndPOST. Of course, you will be only using the public one; the private one is just for encapsulating a functionality needed for the public one … never mind … you only call the public one and voila … you are done!

Shown below is the use of this method:

NameValueCollection data = new NameValueCollection();
data.Add("v1", "val1");
data.Add("v2", "val2");
HttpHelper.RedirectAndPOST(this.Page, "http://DestUrl/Default.aspx", data);

v1 and v2 will be POSTed to the destination URL with redirection; redirection means that you will be redirected to the destination URL and any postbacks there will occur successfully since you are completely transferred there.

But, how does the RedirectAndPOST method work to do the desired trick?!

/// <summary>
/// POST data and Redirect to the specified url using the specified page.
/// </summary>
/// <param name="page">The page which will be the referrer page.</param>
/// <param name="destinationUrl">The destination Url to which
/// the post and redirection is occuring.</param>
/// <param name="data">The data should be posted.</param>
/// <Author>Samer Abu Rabie</Author>

public static void RedirectAndPOST(Page page, string destinationUrl, 
                                   NameValueCollection data)
{
//Prepare the Posting form
string strForm = PreparePOSTForm(destinationUrl, data);
//Add a literal control the specified page holding 
//the Post Form, this is to submit the Posting form with the request.
page.Controls.Add(new LiteralControl(strForm));
}

As you can see … we prepare the POST form which is an HTML form that holds the hidden fields of your POSTed data and a script tag which holds the submit operation of the form .. which will be executed immediately upon the postback.

Below is the code for the PreparePOSTForm method:

/// <summary>
/// This method prepares an Html form which holds all data
/// in hidden field in the addetion to form submitting script.
/// </summary>
/// <param name="url">The destination Url to which the post and redirection
/// will occur, the Url can be in the same App or ouside the App.</param>
/// <param name="data">A collection of data that
/// will be posted to the destination Url.</param>
/// <returns>Returns a string representation of the Posting form.</returns>
/// <Author>Samer Abu Rabie</Author>

private static String PreparePOSTForm(string url, NameValueCollection data)
{
    //Set a name for the form
    string formID = "PostForm";
    //Build the form using the specified data to be posted.
    StringBuilder strForm = new StringBuilder();
    strForm.Append("<form id=\"" + formID + "\" name=\"" + 
                   formID + "\" action=\"" + url + 
                   "\" method=\"POST\">");

    foreach (string key in data)
    {
        strForm.Append("<input type=\"hidden\" name=\"" + key + 
                       "\" value=\"" + data[key] + "\">");
    }

    strForm.Append("</form>");
    //Build the JavaScript which will do the Posting operation.
    StringBuilder strScript = new StringBuilder();
    strScript.Append("<script language="'javascript'">");
    strScript.Append("var v" + formID + " = document." + 
                     formID + ";");
    strScript.Append("v" + formID + ".submit();");
    strScript.Append("</script>");
    //Return the form and the script concatenated.
    //(The order is important, Form then JavaScript)
    return strForm.ToString() + strScript.ToString();
}

Really simple code … for each key value you want to POST, we create a hidden field, we create the form, we then add the script necessary to make the auto submit by calling vPostForm.submit() from the JavaScript code.

Points of Interest

Why put the generated form and script in a literal control and add that control to the requesting page?! Well … the idea basically is to have a form which makes an auto submit of the values by itself without triggering it … we created that form and its script …now we need to make it run … we do that by adding that piece of code to a Literal control on which we will display its contents with no tags! Yes … no tags … that’s the trick … so the form and script will be displayed in the request. Now, since we are posting back to the same page … the contents (our form and script) will run successfully. When it runs, the submit process happens and the auto-postback with our data occurs to the destination URL as we have specified Smile | :)

If I am asked what the drawbacks of this solution are, I would say maybe one drawback … which is that if the client is disabling JavaScript on the browser … then this wouldn’t work. I haven’t tried that … but I expect so … for me, this is a big step and an important solution that helps me a lot to solve a lot of problems Smile | :)

I hope I was clear enough in my explanation … since it requires a deep understanding of the ASP.NET page life cycle and understanding of the postback concepts of a page.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s