Easiest way to parse "querystring" formatted data
Asked Answered
G

8

37

With the following code:

string q = "userID=16555&gameID=60&score=4542.122&time=343114";

What would be the easiest way to parse the values, preferably without writing my own parser? I'm looking for something with the same functionality as Request.querystring["gameID"].

Galantine answered 14/8, 2012 at 16:41 Comment(0)
A
89

Pretty easy... use the HttpUtility.ParseQueryString method.

Untested, but this should work:

var qs = "userID=16555&gameID=60&score=4542.122&time=343114";
var parsed = HttpUtility.ParseQueryString(qs);
var userId = parsed["userID"]; 
//  ^^^^^^ Should be "16555".  Note this will be a string of course.
Andersen answered 14/8, 2012 at 16:43 Comment(7)
Thanks! Looks good, I'm having trouble decoding the horrible example they provided on the MSDN page though, once I have var q = HttpUtility.ParseQueryString("?userID=16555&gameID=60&score=4542.122&time=343114"); how do I retrieve a specific value?Galantine
I can't find System.Net.HttpUtility net Core 1.0 frameworkLicense
Seems like they removed it. Reference the answer here for a solution: #29993348Andersen
The Nancy library also includes Nancy.Helpers.HttpUtility.ParseQueryString.Barbi
Note that ParseQueryString fails is there is more than 1024 key-value pairs in the string.Quenna
@Quenna if you’ve got 1025 keys in a query string, I’d argue that you’ve got bigger problems 😉Andersen
@ChrisShain Well, there is e.g. one Paypal API that returns transactions data as a huge url-encoded string of key-value pairs. It easily exceeds 1024.Quenna
K
23

You can do it with linq like this.

string query = "id=3123123&userId=44423&format=json";

Dictionary<string,string> dicQueryString = 
        query.Split('&')
             .ToDictionary(c => c.Split('=')[0],
                           c => Uri.UnescapeDataString(c.Split('=')[1]));

string userId = dicQueryString["userID"];

Edit

If you can use HttpUtility.ParseQueryString then it will be a lot more straight forward and it wont be case-sensitive as in case of LinQ.

Kerns answered 14/8, 2012 at 16:51 Comment(7)
That works in this specific case, but it's not a generic solution because it doesn't do percent-decoding.Fall
Right @Francis Avila, then it will need more modification in query.Kerns
This is a good solution if you need to parse query strings outside of the System.Web context.Dna
This preserves case, unlike ParseQueryString.Piggin
And what happens when you have a query string like a=1&a=2&a=3? That is valid, as is a=1;a=2;a=3. Use HttpUtility.ParseQueryString. It handles these and other oddities.Fisk
I came here because HttpUtility.ParseQueryString() performed the decoding. this solution here works for me.Malkin
@JimMischel to .ToLookup rather than .ToDictionary to handle "duplicate keys"Compensatory
T
7

As has been mentioned in each of the previous answers, if you are in a context where you can add a dependency to the System.Web library, using HttpUtility.ParseQueryString makes sense. (For reference, the relevant source can be found in the Microsoft Reference Source). However, if this is not possible, I would like to propose the following modification to Adil's answer which accounts for many of the concerns addressed in the comments (such as case sensitivity and duplicate keys):

var q = "userID=16555&gameID=60&score=4542.122&time=343114";
var parsed = q.TrimStart('?')
    .Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
    .Select(k => k.Split('='))
    .Where(k => k.Length == 2)
    .ToLookup(a => a[0], a => Uri.UnescapeDataString(a[1])
      , StringComparer.OrdinalIgnoreCase);
var userId = parsed["userID"].FirstOrDefault();
var time = parsed["TIME"].Select(v => (int?)int.Parse(v)).FirstOrDefault();
Telestich answered 1/2, 2017 at 13:40 Comment(1)
Ignores single item arguments, which can sometimes also appear: arg1&arg2&arg3Arbour
F
5

If you want to avoid the dependency on System.Web that is required to use HttpUtility.ParseQueryString, you could use the Uri extension method ParseQueryString found in System.Net.Http.

Note that you have to convert the response body to a valid Uri so that ParseQueryString works.

Please also note in the MSDN document, this method is an extension method for the Uri class, so you need reference the assembly System.Net.Http.Formatting (in System.Net.Http.Formatting.dll). I tried installed it by the nuget package with the name "System.Net.Http.Formatting", and it works fine.

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();
Farfetched answered 16/8, 2017 at 14:30 Comment(3)
Not sure this works...Uri doesn't have a ParseQueryString method attached to it when I try this, my code: var collection = new System.Uri(url).ParseQueryString();Delinda
@TrevorHart Did you make sure to add a reference to System.Net.Http and to add the System.Net.Http namespace?Farfetched
I did, I ended up just writing my own parser.Delinda
P
4

How is this

using System.Text.RegularExpressions;

// query example
//   "name1=value1&name2=value2&name3=value3"
//   "?name1=value1&name2=value2&name3=value3"
private Dictionary<string, string> ParseQuery(string query)
{
    var dic = new Dictionary<string, string>();
    var reg = new Regex("(?:[?&]|^)([^&]+)=([^&]*)");
    var matches = reg.Matches(query);
    foreach (Match match in matches) {
        dic[match.Groups[1].Value] = Uri.UnescapeDataString(match.Groups[2].Value);
    }
    return dic;
}
Pals answered 5/11, 2018 at 11:22 Comment(1)
Thanks!! Does it support single item arguments, as metioned by @Arbour 's comment above? Ignores single item arguments, which can sometimes also appear: arg1&arg2&arg3Rogan
S
3

For .NET Core there is Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery

var queryString = QueryHelpers.ParseQuery("?param1=value");
var queryParamValue = queryString["param1"];

Code snippet modified from trackjs.com:

South answered 17/5, 2022 at 16:18 Comment(0)
I
1

System.Net.Http ParseQueryString extension method worked for me. I'm using OData query options and trying to parse out some custom parameters.

options.Request.RequestUri.ParseQueryString();

Seems to give me what I need.

Isolated answered 4/8, 2019 at 22:4 Comment(0)
R
0

HttpUtility.ParseQueryString will work as long as you are in a web app or don't mind including a dependency on System.Web. Another way to do this is:

// NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(queryString);

NameValueCollection nameValueCollection = 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();

      nameValueCollection.Add(key, val);
   }
}
Renitarenitent answered 26/4, 2022 at 14:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.