• request.querystring("id")与request("id")的区别以及需要注意的编码问题


    转自:http://www.cnblogs.com/qyz123/archive/2006/12/11/589221.html

    request.querystring("id")与request("id")的区别

    一下问题一天遇到2次,复制过来以供下次参考,一般来说还使用万能的request("id")比较好

    Request从几个集合取数据是有顺序的,从前到后的顺序依次是 QueryString,Form,最后是ServerVariables。Request对象按照这样的顺序依次搜索这几个集合中的变量,如果有符合的就中止,后面的就不管了。

    现在我们来分析下你得问题.
    假设有个页面 test.asp?id=111
    这里我们的页面是用GET的方法.这时用request.querystring("id")与request("id")是一样得,应该如果不指定REQUEST得集合,首先就会从Querystring搜索.

    而如果我们的页面是用的是POST的方法发送数据给test.asp,那么用request.querystring("id")是不行的了(他只能取GET),而要用request.from("id"),而如果还用request("id")他也能取到数据,但先检测QUERYSTRING的值,显然速度就慢了.

    下面是个检测的例子你可以看看:
    <%
    If Request("submit")<>"" then
    Response.Write "直接取:"& Request("username") & "<br>"
    Response.Write "取Get:" & Request.QueryString("username") & "<br>"
    Response.Write "取Post:" & Request.Form("username") & "<br>"
    End if
    %>
    <form name=form1 action="" method=post>
    <input type=test name="username" value="postuser">
    <input type=submit name="submit" value="test">
    </form>

    转自http://blog.joycode.com/ghj/archive/2007/12/07/112382.aspx

    使用 Request.QueryString 接受参数时,跟编码有关的一些问题 

    我们先来看以下几个请求,看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

  • 相关阅读:
    CodeBlocks下载与安装教程
    Delphi 资源管理器套件
    做了一个 62 进制的简单实现
    关于 TRegEx.Split()
    Delphi 的链式代码
    在Linux上编译dotnet cli的源代码生成.NET Core SDK的安装包
    尝试解决在构造函数中同步调用Dns.GetHostAddressesAsync()引起的线程死锁
    .NET Core中遇到奇怪的线程死锁问题:内存与线程数不停地增长
    将asp.net core站点发布到IIS上遇到的问题
    .NET Core 构建配置文件从 project.json 到 .csproj
  • 原文地址:https://www.cnblogs.com/wangpei/p/1415422.html
Copyright © 2020-2023  润新知