ASP.NET 中 POST 數據並跳轉頁面(譯自 Redirect and POST in ASP.NET)



本文翻譯自 Samer Abu Rabie 的 《Redirect and POST in ASP.NET

簡介

       在實際項目中,我們會遇到這樣一種應用場景:我們需要與第三方的應用程序通信,在某些特定的情形下,我們不得不使用 POST 請求而非 GET 請求傳遞信息。

背景

       起初,這個問題看起來很簡單,但實際並不是那樣。我很努力地尋求這個問題的解決方法,仔細谷歌搜索之後發現並沒有讓我滿意的較好解決方案。讓我們先來看看向指定的目的URL發送數據(包括POST和GET)有哪些可選方法:

      1. Response.Redirect: 這是一個被廣泛應用的通用方法,但在ASP.NET中此方法只能進行GET傳參,無法進行POST傳參。

      2. Server.Transfer: 這個方法確實是POST數據而非GET,但是很不幸,此方法只適用於請求源與目標地址在同一個應用程序中的情形;並且,當你使用此方法向第三方應用程序發送請求時,此方法並不奏效。

      3. 使用 HttpWebRequest: 這是另一種從工作項目創建整個請求的方法,你可以指定內容,及內容類型,並把用“&”連接的數據寫入一個串聯的表單中,然後把內容轉換爲 byte 數組並通過調用 GetResponse() 方法提交。它會產生一個POST請求嗎?是的,當然會。它會重定向到目的URL嗎?不,它不會跳轉。即使如此,你仍然可以將響應流通過瀏覽器渲染給用戶,並且用戶將會看到極好的目標頁面,但是在這個渲染後的頁面上的任何動作都會崩潰,因爲你現在引用的是和請求相同的源地址——都在你的應用程序內。所以在渲染出的頁面的任何回發請求都會響應爲”404,頁面未找到”。(爲什麼呢?一定要記得默認的PostBack特性即總是把請求回發給當前頁面)。

      4. 使用 WebClient: 這個方法是以上所列方法中我比較喜歡的一個,因爲它夠簡單。創建一個WebClient 對象,賦給它目標Url地址,調用 UploadValues 方法——此方法需要一個 name-value 集合作爲參數(此集合包含了你所有的POST數據),渲染響應流,向目標URL發起的POST請求很完美;但是像上一個方法一樣,你又遇到了相同的情形,引用與請求是相同的源地址,所以任何POST請求都會報404錯誤。

      5. HTML Submit button with POST form: 這是向任何一個 URL POST 數據的標準方法,無論是你本地的應用程序還是第三方應用,但是這將限制你有一個提交按鈕,比如:<input type="submit"/>,當然這個按鈕將無法執行任何服務器端事件,並且你不得不以某種方式按下這個按鈕。

      注意:如果你有其他方法,請繼續使用,我已經將我所見全盤托出。

      現在,讓我們來想象一下,我有一個 Response.Redirect 方法,並且我可以通過POST方式傳遞一個數據集合,是不是很炫?我想這肯定棒極了~

      現在,整個目標是,擁有一個方法能提交一個數據集合,並且所有數據都是以POST方式提交到指定URL的。

使用代碼

      本文中我附上了一個文件,裏面包含了一個叫作“HttpHelper”的類。這個類只有兩個方法:一個私有方法 PreparePOSTForm 和一個公共方法 RedirectAndPOST。當然,你將只能使用那個公共方法;那個私有方法只是爲了封裝公共方法所需的功能。

      下面展示具體的使用方法:

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

      v1 和 v2 將會以 POST 請求方式傳遞到指定的URL並且跳轉到此地址;重定向意味着一旦傳輸徹底完成頁面將會被指向目的URL並且一切回發請求都將成功發生。

      但是,RedirectAndPOST 是怎麼工作的呢?

/// <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));
}

      如你所見,我們用一個包含了多個隱藏域的 HTML 表單來保存將要進行 POST 的數據,以及一個包含了提交(Submit)操作的 Javascript 腳本標籤用於觸發回發操作,腳本將在回發前執行。

      下面是 PreparePOSTForm 方法:

/// <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();
}

      真的是非常簡單的代碼……對於每一個想提交的數據, 我們創建了一個隱藏域來保存它的值,我們添加了必要的腳本,通過 vPostForm.submit() 來使表單完成自動提交操作。

   可以到本文頂部的原文中下載演示代碼,也可以點擊這裏下載:HttpHelper

發佈了4 篇原創文章 · 獲贊 3 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章