QueryString是否真的不区分大小写?

时间:2015-08-04 15:54:11

标签: c# asp.net-mvc asp.net-mvc-5

我正在支付平台上工作,为了响应付款,我的听众会收到一个简单的GET调用,其中包含查询字符串中的一些参数:

  

http://localhost/mytest/listener?TIMECREATED=04.08.2015+12%3A22%3A27&statoattuale=OK&PREVIOUSSTATE=IN&CURRENTSTATE=payment_approved&tipomessaggio=PAYMENT_STATE& DESCRIZIONE =坎比奥+ DI + STATO&安培; datacreazione = 2015年8月4日+ 12%3A22%3A27&安培;的 stabilimento = XXXXXX&安培;的 MerchantNumber = XXXXXX&安培;的 descrizione =坎比奥+ DI + STATO&安培; OBJECT =付款&安培; TIMEGENERATED = 2015年8月4日+ 12%3A23%3A17&安培;的 MERCHANTNUMBER = XXXXXX&安培; statoprecedente = IN&安培;商家帐户= XXXXXX&安培; numeroOrdine = myOrderNo&安培; numeroCommerciante = XXXXXX&安培; datagenerazione = 2015年8月4日+ 12%3A23%3A17&安培; ORDERNUMBER = myOrderNo&安培;的 Stabilimento = XXXXXX&安培;的 MAC = CaWJiRCxbWH%2FsNFMvHUD2A%3D%3D&安培;的 MAC = AnsEvRHkvMwRL%2FgehVtnhA%3D%3D

当我检查Request.QueryString我得到的是一堆乱七八糟的命令和案例。似乎它们在第一次出现的情况下通过调整后的案例进行了重新排序。像这样:

  

TIMECREATED = 2015年8月4日   12:22:27&安培; statoattuale = OK&安培; PREVIOUSSTATE = IN&安培; CURRENTSTATE = payment_approved&安培; tipomessaggio = PAYMENT_STATE&安培;的 DESCRIZIONE =坎比奥   DI STATO& DESCRIZIONE = CAMBIO DI STATO& datacreazione = 04.08.2015   12:22:27&安培;的 stabilimento = XXXXXX&安培;的 stabilimento = XXXXXX&安培;的 MerchantNumber = XXXXXX&安培;的 MerchantNumber = XXXXXX&安培; OBJECT =付款&安培; TIMEGENERATED = 2015年8月4日   12:23:17&安培; statoprecedente = IN&安培;商家帐户= 999988801&安培; numeroOrdine = myOrderNo&安培; numeroCommerciante = XXXXXX&安培; datagenerazione = 2015年8月4日   12:23:17&安培; ORDERNUMBER = myOrderNo&安培;的 MAC = CaWJiRCxbWH / sNFMvHUD2A ==&安培;的 MAC = AnsEvRHkvMwRL / gehVtnhA ==

对我而言,它看起来像一个bug,因为RFC3986声明:

  

当URI使用通用语法的组件时,组件   语法等价规则总是适用;即,该计划和   host不区分大小写,因此应该归一化为   小写。例如,URI是   相当于http://www.example.com/。另一种通用语法   除非特别说明,否则假定组件区分大小写   该计划另有规定(见第6.2.3节)。

目前我通过手动解析Url.Query解决了我的问题,但我仍然不认为Request.QueryString的行为是正确的。

有人可以对此事有所了解吗?

1 个答案:

答案 0 :(得分:3)

不幸的是,API并没有提供一种方法来使Request.QueryString集合区分大小写(或Request.HeadersRequest.Form集合,就此而言。)

然而,通过反思进行一些逆向工程,并不难做到。

public class CaseSensitiveQueryStringCollection : System.Collections.Specialized.NameValueCollection
{
    public CaseSensitiveQueryStringCollection(string queryString, bool urlencoded, System.Text.Encoding encoding)
        // This makes it case sensitive, the default is StringComparer.OrdinalIgnoreCase
        : base(StringComparer.Ordinal)
    {
        if (queryString.StartsWith("?"))
        {
            queryString = queryString.Substring(1);
        }

        this.FillFromString(queryString, urlencoded, encoding);
    }

    internal void FillFromString(string s, bool urlencoded, System.Text.Encoding encoding)
    {
        int num = (s != null) ? s.Length : 0;
        for (int i = 0; i < num; i++)
        {
            int startIndex = i;
            int num4 = -1;
            while (i < num)
            {
                char ch = s[i];
                if (ch == '=')
                {
                    if (num4 < 0)
                    {
                        num4 = i;
                    }
                }
                else if (ch == '&')
                {
                    break;
                }
                i++;
            }
            string str = null;
            string str2 = null;
            if (num4 >= 0)
            {
                str = s.Substring(startIndex, num4 - startIndex);
                str2 = s.Substring(num4 + 1, (i - num4) - 1);
            }
            else
            {
                str2 = s.Substring(startIndex, i - startIndex);
            }
            if (urlencoded)
            {
                base.Add(HttpUtility.UrlDecode(str, encoding), HttpUtility.UrlDecode(str2, encoding));
            }
            else
            {
                base.Add(str, str2);
            }
            if ((i == (num - 1)) && (s[i] == '&'))
            {
                base.Add(null, string.Empty);
            }
        }
    }
}

用法

var query = new CaseSensitiveQueryStringCollection(
    HttpContext.Current.Request.Url.Query, 
    true, 
    System.Text.Encoding.UTF8);

当您使用?MAC=123&mac=456之类的查询字符串时,您可以看到它们是分开的。