.NET에서 쿼리 문자열을 NameValueCollection으로 구문 분석하는 방법


186

나는 같은 문자열을 구문 분석하고 싶습니다 p1=6&p2=7&p3=8NameValueCollection.

Page.Request객체에 액세스 할 수 없을 때 가장 우아한 방법은 무엇입니까 ?

답변:


356

이를위한 내장 .NET 유틸리티가 있습니다 : HttpUtility.ParseQueryString

// C#
NameValueCollection qscoll = HttpUtility.ParseQueryString(querystring);
' VB.NET
Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring)

다음을 교체해야 할 수 있습니다 querystringnew Uri(fullUrl).Query.


26
Omar, ASP.NET 4에서는 작동하지 않았으며 "para"대신 " stackoverflow.com?para " 키를 반환했습니다 . 그래서 올바르게 작동하는 HttpUtility.ParseQueryString (new Uri (fullUrl) .Query)을 사용하고 있습니다.
Michael

2
qscoll [ "p1"], qscoll [ "p2"] 및 qscoll [ "p3"]
SMUsamaShah

5
ParseQueryString은 클라이언트 프로파일에 포함되어 있지 않기 때문에 데스크톱 응용 프로그램에서 사용하기에는 매우 좋지 않습니다. 하나의 간단한 방법을 사용하기 위해 클라이언트 컴퓨터에 100M의 추가 라이브러리를 설치하는 이유는 무엇입니까? 그러나 Microsoft에는 더 나은 아이디어가없는 것 같습니다. 유일한 방법은 자체 메소드를 구현하거나 오픈 소스 구현을 사용하는 것입니다.
Vitalii 2016 년

2
VASoftOnline :이 경우 ParseQueryString의 모노 구현을 사용할 수 있습니다 : github.com/mono/mono/blob/master/mcs/class/System.Web/… 라이센스는 MIT X11입니다 : github.com/mono/mono / blob / master / LICENSE
sw.

3
HttpUtility.ParseQueryStringHttpUtility.ParseQueryString("&X=1&X=2&X=3")결과가 ....X=1,2,3...동일한 이름의 여러 매개 변수를 갖는 것이 드문 일이지만 int [], IEnumerable <int> 등과 같은 컨트롤러 매개 변수를 지원하는 데 필요한 경우를 제외하고는 내 권장 사항입니다 (이러한 매개 변수는 여러 확인란을 지원하는 데 사용될 수 있음) MS 사이트에 따라 "동일한 쿼리 문자열 변수의 여러 항목이 하나의 항목으로 통합됨"을 참조 하십시오 . 이 방법의 수제 버전은 유일한 옵션 일 수 있습니다
dunxz

43

HttpUtility.ParseQueryString은 웹 응용 프로그램에 있거나 System.Web에 대한 종속성을 포함하지 않는 한 작동합니다. 이를 수행하는 다른 방법은 다음과 같습니다.

NameValueCollection queryParameters = new NameValueCollection();
string[] querySegments = queryString.Split('&');
foreach(string segment in querySegments)
{
   string[] parts = segment.Split('=');
   if (parts.Length > 0)
   {
      string key = parts[0].Trim(new char[] { '?', ' ' });
      string val = parts[1].Trim();

      queryParameters.Add(key, val);
   }
}

5
parts.Length> 1, 당신이 호출 할 수있는 부분 [1]로하면 당신은 확인해야합니다
Alexandru Pupsa

2
가치가 없다면? 예를 들어 쿼리 문자열은 다음과 같습니다 ?foo=1&bar. HttpUtility로 구문 분석{ key = null, value = "bar" }
토마스 레베

이것은 HttpUtility.ParseQueryString과 비교할 때 값이 디코딩되지 않기 때문에 (base64로 인코딩 된 값이 보존 됨)
CRice

1
실제로, 여전히 값 '='을 허용해야합니다 (예 : & code = A0SYw34Hj / m ++ lH0s7r0l / yg6GWdymzSCbI2zOn3V4o =는 마지막 '='문자를 제거함). 코드의 일부를 다시 작성하여 '='의 첫 번째 색인을 얻고이를 수정하기 위해 키와 값을 하위 문자열로 나누었습니다 (분할을 사용하는 대신).
CRice

28

많은 답변이 System.Web 에 대한 승인 된 답변의 종속성으로 인해 사용자 정의 예제를 제공 합니다. 로부터 Microsoft.AspNet.WebApi.Client NuGet 패키지로가 UriExtensions.ParseQueryString 도 사용할 수 있습니다, 방법은 :

var uri = new Uri("https://stackoverflow.com/a/22167748?p1=6&p2=7&p3=8");
NameValueCollection query = uri.ParseQueryString();

따라서 System.Web 종속성 을 피하고 직접 롤링하지 않으려는 경우 좋은 옵션입니다.


3
동일한 함수가 System.Net.Http 네임 스페이스에 확장으로 존재하며 (아래 답변 참조) 다른 전체 종속성이 필요하지 않습니다.
jvenema

@jvenema System.Net.Http.Formatting 종속성을 추가하는 위치는 Microsoft.AspNet.WebApi.Client NuGet 패키지를 추가해야만 제공됩니다.
James Skimming

19

전제 조건을 "클라이언트 전용 프레임 워크 하위 집합"으로 제한하면서 ClickOnce 배포의 쿼리 문자열을 구문 분석 할 수 있도록 System.Web에 대한 종속성을 제거하려고했습니다.

나는 rp의 대답을 좋아했다. 논리를 추가했습니다.

public static NameValueCollection ParseQueryString(string s)
    {
        NameValueCollection nvc = new NameValueCollection();

        // remove anything other than query string from url
        if(s.Contains("?"))
        {
            s = s.Substring(s.IndexOf('?') + 1);
        }

        foreach (string vp in Regex.Split(s, "&"))
        {
            string[] singlePair = Regex.Split(vp, "=");
            if (singlePair.Length == 2)
            {
                nvc.Add(singlePair[0], singlePair[1]);
            }
            else
            {
                // only one key with no value specified in query string
                nvc.Add(singlePair[0], string.Empty);
            }
        }

        return nvc;
    }

이것은 Windows Phone에 정말 유용합니다. "NameValueCollection"을 "SortedDictionnary <string, string>"으로
Mike Bryant

4
Dictionary의 NameValueCollection을 전환 할 때주의하십시오. 동일하지 않습니다! 쿼리 문자열은 값이 같은 여러 키를 지원하므로 NameValueCollection도 마찬가지입니다.
Matt DeKrey

7

OLSC 쿼리로 작업 할 때 이미 제공된 것보다 조금 더 다양한 기능이 필요했습니다.

  • 값은 여러 등호를 포함 할 수 있습니다
  • 이름과 값 모두로 인코딩 된 문자 디코딩
  • 클라이언트 프레임 워크에서 실행할 수 있음
  • 모바일 프레임 워크에서 실행할 수 있습니다.

내 해결책은 다음과 같습니다.

Public Shared Function ParseQueryString(ByVal uri As Uri) As System.Collections.Specialized.NameValueCollection
    Dim result = New System.Collections.Specialized.NameValueCollection(4)
    Dim query = uri.Query
    If Not String.IsNullOrEmpty(query) Then
        Dim pairs = query.Substring(1).Split("&"c)
        For Each pair In pairs
            Dim parts = pair.Split({"="c}, 2)

            Dim name = System.Uri.UnescapeDataString(parts(0))
            Dim value = If(parts.Length = 1, String.Empty,
                System.Uri.UnescapeDataString(parts(1)))

            result.Add(name, value)
        Next
    End If
    Return result
End Function

<Extension()>Uri 자체에 기능을 추가하기 위해 그 문제 를 다루는 것은 나쁜 생각이 아닙니다 .


7

System.Web직접 작성하지 않고 추가 NuGet 패키지없이이 작업 을 수행하려면 다음을 수행 하십시오.

  1. 에 참조 추가 System.Net.Http.Formatting
  2. 더하다 using System.Net.Http;
  3. 이 코드를 사용하십시오 :

    new Uri(uri).ParseQueryString()

https://msdn.microsoft.com/en-us/library/system.net.http.uriextensions(v=vs.118).aspx


3
System.Net.Http.Formatting 종속성을 추가하는 위치에서 Microsoft.AspNet.WebApi.Client NuGet 패키지를 추가해야만 제공됩니다.
James Skimming

허, 내 나쁜 자동 설치 된 MVC 프레임 워크와 함께 제공되므로 추가 패키지 (프로그램 파일 (x86) \ Microsoft ASP.NET \ ASP.NET MVC 4 \ 어셈블리 \ System.Net을 추가 할 필요가 없었습니다. Http.Formatting.dll)
jvenema 2016 년

System.Net.Formatting EXTENSION VS2019는 기존의 프레임 워크 참조로부터는 별도의 목록 또는 탭입니다
SQL을 서퍼

3

HttpUtility.ParseQueryString 을 사용해야하는 System.Web에 대한 종속성을 피하려면에서 찾은 Uri확장 메소드를 사용할 수 있습니다.ParseQueryStringSystem.Net.Http .

아직 참조를 추가하지 않은 경우 참조를 추가하십시오 System.Net.Http프로젝트에 .

참고 유효한에 응답 본문을 변환 할 필요가 있다는 Uri정도로 ParseQueryString(에이 System.Net.Http) 작동합니다.

string body = "value1=randomvalue1&value2=randomValue2";

// "http://localhost/query?" is added to the string "body" in order to create a valid Uri.
string urlBody = "http://localhost/query?" + body;
NameValueCollection coll = new Uri(urlBody).ParseQueryString();

System.Net.Formatting EXTENSION VS2019는 확장 참조를 기존 프레임 워크 참조와 분리합니다.
Sql Surfer

2
    private void button1_Click( object sender, EventArgs e )
    {
        string s = @"p1=6&p2=7&p3=8";
        NameValueCollection nvc = new NameValueCollection();

        foreach ( string vp in Regex.Split( s, "&" ) )
        {
            string[] singlePair = Regex.Split( vp, "=" );
            if ( singlePair.Length == 2 )
            {
                nvc.Add( singlePair[ 0 ], singlePair[ 1 ] );    
            }    
        }
    }

5
세미콜론은 http에서 매개 변수 구분 기호로도 사용할 수 있으므로 휠을 다시 만들지 않는 것이 좋습니다.
Matthew Lock

2

방금 Web API Client 에 a ParseQueryString에서 작동하고 a Uri를 반환하는 확장 메소드 가 있음을 깨달았습니다 HttpValueCollection.

var parameters = uri.ParseQueryString();
string foo = parameters["foo"];

1

Request.QueryString에 액세스하십시오. 다른 답변으로 언급 된 AllKeys는 키 배열을 제공합니다.


1

HttpUtility.ParseQueryString(Request.Url.Query)반환은 HttpValueCollection(내부 클래스)입니다. 에서 상속받습니다 NameValueCollection.

    var qs = HttpUtility.ParseQueryString(Request.Url.Query);
    qs.Remove("foo"); 

    string url = "~/Default.aspx"; 
    if (qs.Count > 0)
       url = url + "?" + qs.ToString();

    Response.Redirect(url); 

1

System.Web 종속성을 원하지 않으면 HttpUtility 클래스에서이 소스 코드를 붙여 넣으십시오.

방금 Mono 소스 코드에서 이것을 채찍질했습니다 . HttpUtility와 모든 종속성 (IHtmlString, Helpers, HttpEncoder, HttpQSCollection)이 포함되어 있습니다.

그런 다음을 사용하십시오 HttpUtility.ParseQueryString.

https://gist.github.com/bjorn-ali-goransson/b04a7c44808bb2de8cca3fc9a3762f9c


1

모두가 자신의 솔루션을 붙여 넣는 것 같습니다. 여기 내 것이 있습니다 :-) System.Web저장된 하이퍼 링크에서 id 매개 변수를 가져 오지 않고 클래스 라이브러리에서 이것을 필요로했습니다 .

이 솔루션이 더 빠르고 더 좋아 보이기 때문에 공유하고 싶다고 생각했습니다.

public static class Statics
    public static Dictionary<string, string> QueryParse(string url)
    {
        Dictionary<string, string> qDict = new Dictionary<string, string>();
        foreach (string qPair in url.Substring(url.IndexOf('?') + 1).Split('&'))
        {
            string[] qVal = qPair.Split('=');
            qDict.Add(qVal[0], Uri.UnescapeDataString(qVal[1]));
        }
        return qDict;
    }

    public static string QueryGet(string url, string param)
    {
        var qDict = QueryParse(url);
        return qDict[param];
    }
}

용법:

Statics.QueryGet(url, "id")

1
이 방법의 한 가지 문제 : 쿼리 문자열은 주어진 매개 변수에 대해 둘 이상의 값을 가질 수 있습니다. 이 경우 메서드에서 중복 키 오류가 발생합니다.
Thomas Levesque

예, 적어도 NameValueCollection을 사용하십시오. 중복 키가있는 쿼리 문자열은 완벽하게 합법적입니다.
채드 그랜트

또한 사전은 대소 문자를 구분하므로 X = 1과 x = 1은 다른 키가됩니다. 새로운 사전이 필요합니다 <string, string> (StringComparer.OrdinalIgnoreCase);
채드 그랜트

0

모든 쿼리 문자열 매개 변수의 NameValueCollection에 대한 Request.QueryString.Keys를 실행하십시오.


0

모든 Querystring 값을 얻으려면 다음을 시도하십시오.

    Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring)

Dim sb As New StringBuilder("<br />")
For Each s As String In qscoll.AllKeys

  Response.Write(s & " - " & qscoll(s) & "<br />")

Next s

0
        var q = Request.QueryString;
        NameValueCollection qscoll = HttpUtility.ParseQueryString(q.ToString());

0
let search = window.location.search;

console.log(search);

let qString = search.substring(1);

while(qString.indexOf("+") !== -1)

   qString  = qString.replace("+", "");

let qArray = qString.split("&");

let values = [];

for(let i = 0; i < qArray.length; i++){
   let pos = qArray[i].search("=");
   let keyVal = qArray[i].substring(0, pos);
   let dataVal = qArray[i].substring(pos + 1);
   dataVal = decodeURIComponent(dataVal);
   values[keyVal] = dataVal;
}

-1

VB에서 josh-brown의 C # 버전으로 번역합니다.

private System.Collections.Specialized.NameValueCollection ParseQueryString(Uri uri)
{
    var result = new System.Collections.Specialized.NameValueCollection(4);
    var query = uri.Query;
    if (!String.IsNullOrEmpty(query))
    {
        var pairs = query.Substring(1).Split("&".ToCharArray());
        foreach (var pair in pairs)
        {
            var parts = pair.Split("=".ToCharArray(), 2);
            var name = System.Uri.UnescapeDataString(parts[0]);
            var value = (parts.Length == 1) ? String.Empty : System.Uri.UnescapeDataString(parts[1]);
            result.Add(name, value);
        }
    }
    return result;
}

-2

이것은 내 코드이며 매우 유용하다고 생각합니다.

public String GetQueryString(string ItemToRemoveOrInsert = null, string InsertValue = null )
{
    System.Collections.Specialized.NameValueCollection filtered = new System.Collections.Specialized.NameValueCollection(Request.QueryString);
    if (ItemToRemoveOrInsert != null)
    {
        filtered.Remove(ItemToRemoveOrInsert);
        if (!string.IsNullOrWhiteSpace(InsertValue))
        {
            filtered.Add(ItemToRemoveOrInsert, InsertValue);
        }
    }

    string StrQr = string.Join("&", filtered.AllKeys.Select(key => key + "=" + filtered[key]).ToArray());
    if (!string.IsNullOrWhiteSpace(StrQr)){
        StrQr="?" + StrQr;
    }

    return StrQr;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.