我有一个带有两个操作的 Web API Controller 。一个操作返回数据库中所有实体的列表。第二个操作采用查询字符串参数并过滤实体。
搜索操作被连接起来使用查询字符串参数。它可以工作,但我们遇到了文档工具无法工作的问题,因为操作签名相同(文档工具不考虑查询字符串)。
将搜索参数从查询字符串移动到路由中的属性是否错误?这是一种可以接受的方法吗?会导致我没有考虑的问题吗?
目前,这是我使用的 URL:
domain.com/api/entities?q=xyz
我正在考虑转向基于路由的方法:
domain.com/api/entities/xyz
如果您要实现搜索功能或需要多个可选参数 的其他类型的功能,最好使用查询字符串参数。您可以提供全部、部分或一个都不提供,然后将它们按任何顺序排列,它就会正常工作。
// 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
另一方面,如果您使用 URL 路径和路由,则只有在其右侧没有其他参数时,该参数才是可选的。
// 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
customizing routing to be able to pass optional values in any order 是可能的,但是当查询字符串自然适合这种情况时,这似乎还有很长的路要走。
另一个要考虑的因素是放入 URL 的值是否包含需要编码的 unsafe characters。对 URL 的 path 进行编码是一种糟糕的形式,有时甚至是不可行的,但是对于可以放入查询字符串中的编码字符类型的规则更为宽松。由于 URL 不允许空格,因此更适合用查询字符串中的空格对多词文本搜索字段进行编码(按原样保留),而不是试图找到一种解决方案来用-
放入查询字符串,然后在运行查询时必须将其改回服务器端的空格。
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)
最后,另一个值得考虑的选择是使用 POST 而不是 GET,因为这意味着这些值根本不需要在 URL 中。