I have a Web API controller with two actions. One action returns a list of all entities from the database. The second action takes a query string parameter and filters the entities.
The search action is wired up to use the query string parameter. It works but we encountered an issue with a doc tool not working since the action signatures are the same (the doc tool does not take into account the query string).
Is it wrong to move the search parameter from the query string to an attribute in the route? Is this an acceptable approach? Will is cause problems I'm not thinking about?
Currently, this is a URL I use:
domain.com/api/entities?q=xyz
I'm considering moving to a route-based approach:
domain.com/api/entities/xyz
If you are implementing a search feature, or other type of feature where you need to have multiple optional parameters, it is better to use query string parameters. You can supply all of them, some of them, or none of them and put them in any order, and it will just work.
// Anything Goes
/controller/action?a=123&b=456&c=789
/controller/action?c=789&a=123&b=456
/controller/action?b=456&c=789
/controller/action?c=789
/controller/action
On the other hand, if you use URL paths and routing, a parameter can only be optional if there is not another parameter to the right of it.
// OK
/controller/action/123/456/789
/controller/action/123/456
/controller/action/123
// Not OK
/controller/action/123/456/789
/controller/action/456/789
/controller/action/789
It is possible by customizing routing to be able to pass optional values in any order, but it seems like a long way to go when query strings are a natural fit for this scenario.
Another factor to consider is whether the values being put into the URL have unsafe characters in them that need to be encoded. It is poor form and sometimes not feasible to encode the path of the URL, but the rules of what types of encoded characters that can be put into a query string are more relaxed. Since URLs don't allow spaces, it is a better fit for a multiple word text search field to be encoded with the space in the query string (preserving it as is) rather than trying to find a solution to swapping out the space with a -
to put into the query string and then having to change it back to a space on the server side when running the query.
search = "foo bar"
// Spaces OK
/controller/action?search=foo%20bar (works fine and server is able to interpret)
// Spaces Not OK
/controller/action/foo bar/ (not possible)
/controller/action/foo%20bar/ (may work, but a questionable design choice)
/controller/action/foo-bar/ (may work, but requires conversion on the server)
Finally, another choice worth considering is using POST instead of GET, as that would mean these values wouldn't need to be in the URL at all.