<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    http://www.tkk7.com/ebecket 返還網
    隨筆-140  評論-11  文章-131  trackbacks-0

     

    我們先來看以下幾個請求,看a.aspx 頁面用Request.QueryString接受到的是啥信息?

      頁面URL Request.QueryString["info"]接受到的值
    案例一 a.aspx?info=%25

    %

    案例二 a.aspx?info=%bc%bc%ca%f5

    ????

    情況分析:

    案例一

    a.aspx?info=%25 為何 Request.QueryString["info"]接受到的值是 % ,而不是 %25,是因為Request.QueryString 替我們在接受到值后,做了一次URL解碼。 HttpUtility.UrlDecode("%25")  的計算結果就是 %

    上面的這個案例一雖然看起來很簡單。但是我們在一些特殊場景時候,就會因為這個而極度郁悶。

    比如以下幾種情況:

    你有一個自己的加密算法,而這個加密算法,某些情況下會計算出帶百分號的結果,而這個結果你是要通過URL參數的方式傳遞給其它頁面的。
    這時候你就苦惱的發現,某些時候某個功能就不能用。

    如果解決案例一碰到的情況呢?

    解決方案一:

    把需要傳遞的參數傳遞前作一次 HttpUtility.UrlEncode ,
    記得是按照 UTF-8 的編碼的 UrlEncode 。這樣如果我們希望客戶端接受到的是 %25  就應該傳遞的是 %2525 。

    切記,不可在接受方每次接受后,自作聰明的都做一次 UrlEncode 。而是在發送方做 UrlEncode 。
    如果接受方接受后作 UrlEncode 的話,就會出現下面情況:
    發送方發送 a.aspx?info=%25 ,這時候如果接受方  接受后作 UrlEncode 的話,一切正確
    發送方發送 a.aspx?info=% ,這時候如果接受方  接受后作 UrlEncode 的話,則就亂了。

    另:這套方案中切記, UrlEncode  和 UrlDecode 的次數應該一一對應。不能多一次,也不能少一次。
    有人就會說,這還會出現次數不對應么? 比如下面情況,一個不留意就很可能出現次數不對應。而出現不是你所期望的情況。
    比如我們有這樣類似的功能:

    a.aspx 頁面中,根據傳入的 from 參數,自動跳轉到 from 參數(用Request.QueryString["from"]來接受這個參數)設置的頁面。
    b.aspx 頁面也是同樣的邏輯,根據傳入的 from 參數(用Request.QueryString["from"]來接受這個參數),自動跳轉到指定的頁面。
    c.aspx 頁面也是同樣的邏輯,根據傳入的 from 參數(用Request.QueryString["from"]來接受這個參數),自動跳轉到指定的頁面。


    這樣我們就可能書寫下面的鏈接地址:
    a.aspx?from=b.aspx 
    a.aspx?from=b.aspx?from=c.aspx
    a.aspx?from=b.aspx?from=c.aspx?from=http://blog.joycode.com/ghj/

    下面再復雜一點,我給下面幾個鏈接,其中都有 a 這個參數,請告訴我 a 這個參數是被那個頁面接受到了?
    說明:  HttpUtility.UrlEncode("&")  == "%26"     HttpUtility.UrlEncode("%")  == "%25"

    地址 a 參數會被那個頁面接受到
    a.aspx?from=b.aspx?from=c.aspx&a=1 a 參數被 a.aspx 頁面接受到了
    a.aspx?from=b.aspx?from=c.aspx%26a=1 a 參數被 b.aspx 頁面接受到了
    a.aspx?from=b.aspx?from=c.aspx%2526a=1 a 參數被 c.aspx 頁面接受到了

    如果想不明白,就想想下面這句話
    每一次用 Request.QueryString 獲取參數時候,就作了一次 HttpUtility.UrlDecode。

    解決方案二:

    不用 Request.QueryString ,而是自己實現一個獲取查詢參數的方法。細節我在案例二講完后再告訴大家,因為這個解決方案也處理了案例二的一些情況。

    案例二

    a.aspx?info=%bc%bc%ca%f5 傳給我們的信息其實是使用 GB2312 編碼后的“技術” 這兩個漢字。
    不信,你可以用下面表達式計算的結果就是 %bc%bc%ca%f5
    HttpUtility.UrlEncode("技術", System.Text.Encoding.GetEncoding("GB2312"))

    ASP.net 系統內部,在處理 Request.QueryString 等情況時候,都是使用的 UTF-8 的編碼,我們如果不存在多系統并存的問題時候,這個問題一點都不存在。
    但是,當需要跟其它系統交互式后,問題就可能會出現。
    如果你不了解案例二這里情況時,你就會被這個問題苦惱死。

    比如下面這兩個地址提到的問題:

    ASP.net中的Server.UrlEncode函數和ASP中的Server.URLEncode函數返回的值竟然不一樣
    http://blog.joycode.com/ghj/archive/2003/10/20/2992.aspx

    PHP與aspx之間中文通過URL如何傳遞?
    http://topic.csdn.net/u/20071018/19/8a4066af-a08c-4214-91e9-ed4caf977e07.html

    案例二的解決方案
    使用帶編碼的 HttpUtility.ParseQueryString 函數

    就是采用類似下面代碼的方式,來獲得指定格式編碼的查詢文本參數。

               System.Collections.Specialized.NameValueCollection nv =
    System.Web.HttpUtility.ParseQueryString(Request.Url.Query, System.Text.Encoding.GetEncoding("GB2312"));
               Response.Write(nv["Tag"]);

     

    要說我為啥知道上面幾種解決方案,是因為我用 Reflector 看了 Request.QueryString 的實現代碼。在查看代碼時候,我們會看到這樣一個 internal 方法:
    System.Web.HttpValueCollection 類的內部方法:
    internal void FillFromString(string s, bool urlencoded, Encoding encoding)

    這個內部方法實現了,按需解密查詢參數的功能,但是遺憾的是,在QueryString 的處理函數中,強制指定了解析 QueryString 時,必須作一次 HttpUtility.UrlDecode。參看如下代碼:

    public static NameValueCollection ParseQueryString(string query, Encoding encoding)
    {
        ...
        return new HttpValueCollection(query, false, true, encoding);
    }

    如果我們不想采用案例一的解決方案一,我們就需要自己寫一個解析查詢信息的代碼。我們完全可以照抄 System.Web.HttpValueCollection 類的 internal void FillFromString(string s, bool urlencoded, Encoding encoding) 方法來改寫。但郁悶的是:如果你用 Reflector 察看這個函數的實現時候,Reflector 出來的代碼是錯誤的。正確的方法如下:是在施凡幫助下完成的。

    自己實現從 URL 查詢文本 Query 中解析出我們自己需要的文本的方法

    /// <summary>
    /// 根據 URL 中的 查詢文本 Query 解析成一個 NameValueCollection
    /// 在裝配腦袋幫助下 郭紅俊 改編自 System.Web.HttpValueCollection 類的內部方法:
    /// internal void FillFromString(string s, bool urlencoded, Encoding encoding)
    /// </summary>
    /// <param name="query">需要解析的查詢文本</param>
    /// <param name="urlencoded">解析文本時候是否需要URL解碼</param>
    /// <param name="encoding">解析文本時候,按照那種URL編碼進行解碼</param>
    /// <returns></returns>
    public static NameValueCollection FillFromString(string query, bool urlencoded, Encoding encoding)
    {
        NameValueCollection queryString = new NameValueCollection();
        if (string.IsNullOrEmpty(query))
        {
            return queryString;
        }

        // 確保 查詢文本首字符不是 ?
        if (query.StartsWith("?"))
        {
            query = query.Substring(1, query.Length - 1);
        }

        int num1 = (query != null) ? query.Length : 0;
        // 遍歷每個字符
        for (int num2 = 0; num2 < num1; num2++)
        {
            int num3 = num2;
            int num4 = -1;
            while (num2 < num1)
            {
                switch (query[num2])
                {
                    case '=':
                        if (num4 < 0)
                        {
                            num4 = num2;
                        }
                        break;
                    case '&':
                        goto BREAKWHILE;
                }
                num2++;
            }

        BREAKWHILE:

            string name = null;
            string val = null;
            if (num4 >= 0)
            {
                name = query.Substring(num3, num4 - num3);
                val = query.Substring(num4 + 1, (num2 - num4) - 1);
            }
            else
            {
                val = query.Substring(num3, num2 - num3);
            }
            if (urlencoded)
            {

                queryString.Add(HttpUtility.UrlDecode(name, encoding), HttpUtility.UrlDecode(val, encoding));
            }
            else
            {
                queryString.Add(name, val);
            }
            if ((num2 == (num1 - 1)) && (query[num2] == '&'))
            {
                queryString.Add(null, string.Empty);
            }
        }

        return queryString;

    }

    用上面的代碼,我們就可以按需解析自己需要的查詢參數,而不是受限的使用Request.QueryString 。

    小結

          Request.QueryString 替我們件事情:每次接受到參數后,都做 UrlEncode ,并且是按照 UTF-8編碼做的 UrlEncode 。 這在大多數情況下沒有任何問題,但是一些情況下,會給我們帶來麻煩,本文就是分析這些可能給我們帶來麻煩的場景,以及解決方法。

    參考資料:

    使用 Reflector ; 查看代碼時候,碰到的一個Reflector 的bug
    http://blog.joycode.com/ghj/archive/2006/12/06/88646.aspx

    解密不同編碼的的參數。
    http://blog.joycode.com/ghj/archive/2006/04/19/74894.aspx

    posted on 2009-10-16 14:17 becket_zheng 閱讀(284) 評論(0)  編輯  收藏 所屬分類: web前端開發
    主站蜘蛛池模板: 免费久久精品国产片香蕉| 日本zzzzwww大片免费| 免费黄色大片网站| 亚洲成aⅴ人片在线观| 97精品免费视频| 亚洲天堂中文字幕| 午夜视频免费在线观看| 亚洲欧洲∨国产一区二区三区| 污网站在线免费观看| 国产hs免费高清在线观看| 亚洲AV日韩综合一区| 免费在线看片网站| 九九综合VA免费看| 自拍偷自拍亚洲精品第1页| 岛国精品一区免费视频在线观看| 亚洲欧洲精品成人久久奇米网 | 亚洲精品国产福利片| 久久精品一本到99热免费| 久久亚洲sm情趣捆绑调教| 成人黄色免费网站| 亚洲乱码在线观看| 国产免费av片在线播放| 男女猛烈xx00免费视频试看| 亚洲色婷婷综合开心网| sss在线观看免费高清| 亚洲Av永久无码精品三区在线| 日本三级在线观看免费| 久久久久亚洲精品日久生情| 青娱乐免费视频在线观看| 亚洲av午夜电影在线观看 | 日韩av无码久久精品免费| 亚洲高清视频免费| 成年女人毛片免费视频| 日韩一级片免费观看| 久久精品九九亚洲精品天堂| h视频在线观看免费完整版| 亚洲大码熟女在线观看| 在线a亚洲v天堂网2019无码| 在线观看永久免费| 久久亚洲AV成人无码国产电影| 亚洲最大AV网站在线观看|