Как получить имя / значение Request.Querystring, используя For Each Loop, но в том же порядке? - PullRequest
0 голосов
/ 17 марта 2019

Я пытался получить имя / значение строки запроса, используя цикл For Each, согласно @ kloarubeek ответа, показанного в → Request.Querystring (variablevalue) возможно ? следующим образом:

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

Но он возвращает элементы не в порядке отправки , , например :
если мой queryString равен:

"Элемент1 = 1 & Элемент2 = 2 & Item3 = 3 & Item4 = 4"

затем для каждого цикла возвращает:

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

Мне удалось обойти его, разделив его на Array , а затем зацикливать внутри этого массива и повторно делить каждый элемент на имя и значение. но это длинное и не очень эффективное кодирование.

Так есть ли лучший и более короткий способ получить querystring's name/value, используя For Each Loop, но in the same order?

Ответы [ 2 ]

0 голосов
/ 17 марта 2019

Ваш оператор 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 < br /> & 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, два
item3: 3
item4: четыре, 4
item5: 5


EDIT: Я предполагал, что ошибка была в IIS или ASP, переупорядочивающем заголовок строки запроса (как-нибудь?), Но после просмотра вашего комментария, где вы сказали if I target the querystring with the index number it gets the order right, заголовки, очевидно, правильны и ошибка лежит в методе for each (как указано в другом ответе). Гораздо более простым решением было бы разделить необработанный заголовок строки запроса (вместо использования 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

%>
0 голосов
/ 17 марта 2019

Объект QueryString является коллекцией NameValueCollection, которая в соответствии с MSDN:

Коллекции этого типа не сохраняют порядок элементов, и при перечислении коллекции особый порядок не гарантируется.

Так что он не поддерживает получение в том же порядке, что и URL.

Отредактировано для добавления опции:

Как говорится, похоже, что единственный способ - это проанализировать URL. В этом вопросе stackoverflow ( Получить отдельные параметры запроса из Uri ) один из ответов включает в себя раздел, посвященный его синтаксическому анализу с использованием регулярных выражений (все остальные ответы приводят к той же самой NameValueCollection). Вы захотите немного изменить его, так как у класса Dictionary есть та же проблема - несоблюдение порядка. Я бы изменил это так:

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

...