Reputation: 33881
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?
Upvotes: 113
Views: 70478
Reputation: 36060
If you want the first string and are not expecting multiple values just do:
Request.Query["color"][0]
Upvotes: -1
Reputation: 814
Just posting for curious souls and probably little do with question. Just cautionary note.
I found myself in similar issue. There are couple other issues with this type.
If you have query parameter with no value. For example: /products?pageNo=1&pageSize=
You will find yourself getting an exception thrown for pageSize
parameter as Count
property on StringValues
will give you value 1, but underlying _value
is ""
(empty
string) and _values
is null
. Note - Exception happens you are trying to convert or
access values from IQueryCollection)
Using TryGetValue
will get you value safely out of StringValues
but if it is null
(like in case of pageSize
parameter above), You will have hard time figuring out why
can't you convert StringValues
to simple String
or why can not compare with null
to
do further operations on it like validations etc.
To do any checking on StringValues
type, use methods provided by the type.
To check for null or empty use - StringValues.IsNullOrEmpty(StringValues value)
Upvotes: 12
Reputation: 388223
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 soRequest.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);
}
Upvotes: 104
Reputation: 136164
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
Upvotes: 74