Search code examples
foreachasp-classicrequest.querystring

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


I was trying to fetch the Name/Value of a querystring using For Each loop, as per @kloarubeek answer shown in → Request.Querystring(variablevalue) possible? as follows:

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

But it returns the items not in the order sent, for example:
if my queryString is:

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

then the For Each Loop returns:

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

I managed to work around it by splitting it into an Array and then loop inside this array and re-split each item again into name and value. but it's a long and not very efficient coding.

So is there a better and shorter way to fetch the querystring's name/value using the For Each Loop but in the same order?


Solution

  • Your for each statement should loop through the query strings in the order they were passed, it's very strange that it doesn't, I'd never heard of that before. But as your parameters are numbered you can assign them to an array and reorder based on their numerical indicators.

    This is how I would tackle this issue, I don't know if it's shorter than your method of splitting and reordering, but it does seem to be efficient:

    <%
    
        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
    
    %>
    


    Let's take a completely jumbled up query string order:

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

    Output:

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


    Let's do the same, but throw in some additional parameters:

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

    Output:

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

    The additional parameters are ignored


    Finally, let's pass some duplicate parameters:

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

    Output:

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


    EDIT: I assumed the fault was with IIS or ASP reordering the querystring header (somehow?), but after seeing your comment where you said if I target the querystring with the index number it gets the order right the headers are obviously correct and the fault lies within the for each method (as outlined in the other answer). A much simpler solution would be to split the raw querystring header yourself (rather than using for each) and loop through looking for the items:

    <%
    
        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
    
    %>