如何使用 For Each Loop 获取 Name/Value of Request.Querystring 但发送顺序相同?

How to fetch Name/Value of Request.Querystring using For Each Loop but in the same order sent?

我试图使用 For Each 循环获取查询字符串的 Name/Value,根据 @kloarubeek 显示的答案在 → Request.Querystring(variablevalue) possible? 中如下:

For Each Item in Request.QueryString
Response.Write Item & ": " & Request.QueryString(Item) & "<br/>"
Next

但是returns物品不在发送顺序例如
如果我的 queryString 是:

"Item1=1&Item2=2&Item3=3&Item4=4"

然后 For Each Loop returns:

Item1=1
Item3=3
Item2=2
Item4=4

我设法通过将它拆分为一个 数组 来解决它,然后在这个数组中循环并 再次重新拆分每个项目成名称和价值。但这是一个很长而且效率不高的编码。

那么有没有更好更短的方法来获取 querystring's name/value 使用 For Each Loopin the same order?

QueryString 对象是一个 NameValueCollection,根据 MSDN:

Collections of this type do not preserve the ordering of elements, and no particular ordering is guaranteed when enumerating the collection.

因此它不支持按与 url 相同的顺序获取它。

编辑以添加一个选项:

话虽这么说,但看起来唯一的方法就是解析 url。在这个 Whosebug 问题 (Get individual query parameters from Uri) 中,其中一个答案包括使用正则表达式对其进行解析的部分(那里的所有其他答案都导致相同的 NameValueCollection)。您需要稍微修改一下,因为 Dictionary class 也有不遵守顺序的问题。我会把它改成这样:

public static class UriExtensions
{
    private static readonly Regex _regex = new Regex(@"[?&](\w[\w.]*)=([^?&]+)");

    public static List<KeyValuePair<string, string>> ParseQueryString(this Uri uri)
    {
        var match = _regex.Match(uri.PathAndQuery);
        var paramaters = new List<KeyValuePair<string, string>>();
        while (match.Success)
        {
            paramaters.Add(new KeyValuePair(match.Groups[1].Value, match.Groups[2].Value));
            match = match.NextMatch();
        }
        return paramaters;
    }
}

要这样称呼它:

Request.Url.ParseQueryString()

我会注意到我自己还没有测试过这个方法,并且我认为它在另一个问题上被认为是一个很好的答案。

https://docs.microsoft.com/en-us/dotnet/api/system.web.httprequest.querystring?view=netframework-4.7.2 https://docs.microsoft.com/en-us/dotnet/api/system.collections.specialized.namevaluecollection?view=netframework-4.7.2

您的 for each 语句应该按照传递的顺序遍历查询字符串,很奇怪它没有,我以前从未听说过。但是由于您的参数已编号,您可以将它们分配给一个数组并根据它们的数字指示符重新排序。

这就是我解决这个问题的方法,我不知道它是否比你的拆分和重新排序的方法更短,但它看起来确实有效:

<%

    if request.querystring.count > 0 then

        Dim lookFor, queryStrings(), items(), x, y

        ' Specify the query string name to find and reorder. The name should have a numeric suffix.

        lookFor = "item" ' Looking for item1, item2, item3, item4 etc...

        ' Create a 2d array, set the upperbound value to match the number of query strings passed.

        ReDim queryStrings(request.querystring.count-1,1)

        ' Loop through each query string.

        x = 0 : for each item in request.querystring

            ' We're only interested in query strings where the name starts with "item". Use inStr()
            ' with a textual comparison to check, and use replace() to check that the item name has 
            ' a numeric suffix.

            if inStr(1,item,lookFor,1) = 1 AND isNumeric(replace(item,lookFor,"",1,-1,1)) then

                ' Only store the number part of the query string name. This is needed for reordering later.

                queryStrings(x,0) = int(replace(item,lookFor,"",1,-1,1))
                queryStrings(x,1) = request.querystring(item)
                x = x + 1

            end if

        Next

        ' The queryStrings array may contain empty values. We can't use "ReDim Preserve" to resize
        ' a 2d array, so instead let's create another 2d array and set the upperbound value to the
        ' number of items found.

        ReDim items(x-1,1)

        ' Assign the non-empty data from the queryStrings array to the items array.

        y = 0 : for x = 0 to uBound(queryStrings)
            if NOT isEmpty(queryStrings(x,0)) then
                items(y,0) = queryStrings(x,0)
                items(y,1) = queryStrings(x,1)
                y = y + 1
            end if
        next

        ' Reorder the items array.

        Dim temp0, temp1

        for x = uBound(items)-1 to 0 step-1
            for y = 0 to x
                if items(y,0) > items(y+1,0) then
                    temp0 = items(y+1,0)
                    temp1 = items(y+1,1)
                    items(y+1,0) = items(y,0)
                    items(y+1,1) = items(y,1)               
                    items(y,0) = temp0
                    items(y,1) = temp1
                end if
            next
        next

        ' Finally, output the reordered items array.

        for x = 0 to uBound(items)  
            response.write lookFor & items(x,0) & ": " & items(x,1) & "<br>"
        next

    end if

%>


让我们来看一个完全混乱的查询字符串顺序:

?Item3=3
&Item6=6
&Item2=2
&Item7=7
&Item4=4
&Item1=1
&Item5=5

输出:

item1: 1
item2: 2
item3: 3
item4: 4
item5: 5
item6: 6
item7: 7


让我们做同样的事情,但加入一些额外的参数:

?foo1=bar1
&Item2=2
&foo2=bar2
&Item5=5
&Item1=1
&Item3=3
&Item4=4
&foo3=bar3

输出:

item1: 1
item2: 2
item3: 3
item4: 4
item5: 5

忽略附加参数


最后,让我们传递一些重复的参数:

?Item2=2
&Item4=Four
&Item5=5
&Item1=1
&Item2=Two
&Item3=3
&Item4=4

输出:

item1: 1
item2: 2, Two
item3: 3
item4: Four, 4
item5: 5


编辑: 我假设错误是 IIS 或 ASP 重新排序查询字符串 header (不知何故?),但之后看到你说 if I target the querystring with the index number it gets the order right 的评论,header 显然是正确的,错误在于 for each 方法(如其他答案中所述)。一个更简单的解决方案是自己拆分原始查询字符串 header(而不是使用 for each)并循环查找项目:

<%

    Dim splitQS, reSplitQS, x, lookFor : lookFor = "item"

    splitQS = split(Request.QueryString,"&")

    for x = 0 to uBound(splitQS)

        reSplitQS = split(splitQS(x),"=")

        if uBound(reSplitQS) = 1 then

            if inStr(1,reSplitQS(0),lookFor,1) = 1 then

                response.write reSplitQS(0) & ": " &_
                request.QueryString(reSplitQS(0)) & "<br>"

            end if

        end if

    next

%>