Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is StringValues used for Request.Query values?

Let's say I have some url that looks like this: www.myhost.com/mypage?color=blue

In Asp.Net Core, I'd expect to get the color query parameter value by doing the following:

string color = Request.Query["color"];

But it turns out that the Request.Query["color"] returns a value of type StringValues rather than string. Why is that?

Apparently the StringValues type can hold an array of strings and includes support for implicit conversion to string[] which is cool but why is that needed for a query param value?

Having to get the value like this seems odd:

string color = Request.Query["color"].ToString();

And worse, checking for a value to see if a query param is specified can no longer be done like so

  if(Request.Query["color"] == null) { 
      //param was not specified
  }

but instead must be checked like so

 if(Request.Query["color"].Count == 0) { 
      //param was not specified
 }

Since a single query parameter can't have multiple values (as far as I know) why does Request.Query["color"] return a StringValues object rather than a string?

like image 287
RonC Avatar asked Jan 10 '18 13:01

RonC


2 Answers

As already mentioned by others, the type is a StringValues object because technically, multiple values are allowed. While the common practice is to just set a single value, the URI specification does not disallow setting values multiple times. And it’s up to the application to decide how to handle that.

That being said, StringValues has an implicit conversion to string, so you don’t actually need to call ToString() on it, you can just use it as if it was a string. So doing things like Request.Query["color"] == "red", or passing it to a method that expects a string will just work.

And worse, checking for a value to see if a query param is specified can no longer be done like so Request.Query["color"] == null but instead must be checked like so Request.Query["color"].Count == 0

That’s only half true. Yes, in order to check whether a StringValues object is empty, you can check its Count property. You can also check against StringValues.Empty:

Request.Query["color"] == StringValues.Empty

However, the initial “issue” is that Request.Query[x] will always return a non-null StringValues object (so it’s safe to check for any value). If you want to check whether a key exists in the query arguments, you should use ContainsKey:

if (Request.Query.ContainsKey("color"))
{
    // only now actually retrieve the value
    string colorValue = Request.Query["color"];
}

Or alternatively, use TryGetValue:

if (Request.Query.TryGetValue("color", out var colorValue))
{
    DoSomething(colorValue);
}

That all being said, accessing Request.Query is not really necessary most of the times. You should just use make use of model binding instead which will automatically give you the query arguments you need by just having them in the action’s signature:

public ActionResult MyAction(string color)
{
    DoSomething(color);
}
like image 185
poke Avatar answered Oct 31 '22 16:10

poke


Because your query can look like this:

www.myhost.com/mypage?color=blue&color=red&color=yellow

And you get all those color values from the one Request.Query["color"] parameter

like image 65
Jamiec Avatar answered Oct 31 '22 16:10

Jamiec