7

I have a problem where I need to extract a query string parameter from a url. The parameter could be either "Territory" or "territory" or other upper/lower case variations of that word. Although the following works for the first two cases I wonder if there is a better way?

IDictionary<string, string> queryString = HtmlPage.Document.QueryString;

if (queryString.ContainsKey("territory"))
{
    ish.SetDefaultRegion(int.Parse(queryString["territory"]));
    // do something (the same something as below)
}
else if (queryString.ContainsKey("Territory"))
{
    ish.SetDefaultRegion(int.Parse(queryString["Territory"]));
    // do something (the same something as above)
}

I would prefer to insert the query string into the dictionary ignoring case (ie. if the user accidentally typed "TERRITORY" this code would fail, so how can I just test that the word exists regardless of casing?

budi
  • 6,351
  • 10
  • 55
  • 80
rmcsharry
  • 5,363
  • 6
  • 65
  • 108
  • This could help you out. Get the key from the queryString object. Convert it into small case and then compare with "territory". This way you wouldnt have to worry about the casing. – Krishna May 03 '12 at 16:57
  • @Krishna: And how exactly can the key be obtained from the queryString object, if you don't know its case (besides iterating through every key)? – Cameron May 03 '12 at 17:13
  • @Cameron - Thank you for clarifying. That's exactly my issue! – rmcsharry May 04 '12 at 10:31
  • `Request.QueryString["territory"]` is already case-insensitive. It doesn't matter whether it's in the URL as "Territory", "territory", "TeRrItOrY", etc. – Doug S Nov 18 '17 at 20:13
  • @Doug That may well be true but ContainsKey lookup will still fail to match "Territory" and "TeRrItOrY" - hence why, as per the answer, when creating the Dictionary from the QueryString, a case-insensitive key comparer is needed. – rmcsharry Nov 18 '17 at 21:05
  • @rmcsharry: Why do you need to convert the Request.QueryString object to a Dictionary? If you want to know if a key exists in the QueryString object, just do `if (Request.QueryString["TeRriToRy"] != null) {` – Doug S Nov 23 '17 at 18:34
  • The key is user generated, it can therefore be any mix of lower case or upper case. Doing as you suggested will only return true if the casing is exactly as you typed it. Therefore the QueryString needs to be converted to a Dictionary and case-insensitive key comparer used to match all variations of casing that the use might type. And since QueryString is itself a dictionary you cannot simply call toLower on it. – rmcsharry Nov 23 '17 at 20:11

3 Answers3

14

Use a dictionary with a case-insensitive key comparer:

var queryParams = new Dictionary<string, string>(
    HtmlPage.Document.QueryString,
    StringComparer.InvariantCultureIgnoreCase
);

if (queryParams.ContainsKey("territory")) {
    // Covers "territory", "Territory", "teRRitory", etc.
}
Cameron
  • 96,106
  • 25
  • 196
  • 225
  • 1
    Warning: i believe InvariantCultureIgnoreCase is a dangerous choice. it seems OrdinalIgnoreCase is the safe choice. It is my understanding that InvariantCulture treats accentented letters as the same as non accented letters. so i interpret this means 'resumeID' = 'resuméID'. but i understand that OrdinalIgnoreCase treats 'resumeID' and 'resuméID' as different strings. Disclaimer: I have not tested this and don't have the time to do so at this time. Much info on the net is bad advice or just flat wrong, so i'm only posting this a 'be careful of this' and i don't know for sure. :P – Shawn Kovac Dec 31 '15 at 18:12
  • 1
    @Shawn: You know, `OrdinalIgnoreCase` is probably a better default here. But, `InvariantCultureIgnoreCase` certainly does not consider `resumeID` and `resuméID` to be equal ([try it](http://csharppad.com/gist/a1e1d956b09f1b5f52b5)!). I believe it merely does a form of Unicode normalization during the comparison (so, e followed by a combining acute accent would equal the e-with-acute-accent character), whereas `OrdinalIgnoreCase` checks codepoint by codepoint (though I may be wrong too, heh). There's some more info [here](http://stackoverflow.com/q/2749662/21475). – Cameron Jan 01 '16 at 00:50
2

If your QueryString Object is not a dictionary object but instead is something such as a NameValueCollection...

IDictionary<string, string> queryString = QueryString.AllKeys.ToDictionary(k => k.ToLowerInvariant(), k => QueryString[k]);
George
  • 4,323
  • 3
  • 30
  • 33
  • but wud this code break (error) when the querystring contains 'duplicate' keys that only differ in case? So what does this code do when the querystring is 'abc=1&ABC=2'? – Shawn Kovac Dec 31 '15 at 18:16
0

Hello it can be also TeRriTory, in the querystring do a .Tolower()

DadViegas
  • 2,263
  • 16
  • 12