Web API可选参数

84

我有一个带有以下签名的控制器:

[Route("products/filter/{apc=apc}/{xpc=xpc}/{sku=sku}")]
public IHttpActionResult Get(string apc, string xpc, int? sku)
{ ... }

我使用以下URI调用此方法:

  • ~/api/products/filter?apc=AA&xpc=BB
  • ~/api/products/filter?sku=7199123

第一个URI可以正常工作,但第二个URI会有奇怪的副作用。尽管在没有提供参数时,apc和xpc的默认值应该为null,但实际上它们的值是它们的名称。我可以通过添加额外的逻辑来克服这个问题:

apc = (apc == "apc") ? null : apc;
xpc = (xpc == "xpc") ? null : xpc;

这似乎是一种 hack 的方法,而且如果传递的值恰好等于参数名,则可能会出现问题。

有没有一种不会产生这种副作用的定义路由的方法?


3
你在路由模板中提供了默认值,为什么会期望它们是 null 呢? - Kenneth K.
我认为{sku=sku}将查询字符串中的参数映射到方法参数。 - Josh
4
你应该查看 属性路由文档,了解如何使参数变成可选项。这将有助于你更好地理解相关内容。 - Kenneth K.
4个回答

177

我想通了。我过去使用的一个错误示例,教我如何将查询字符串映射到方法参数。

如果有人需要,在查询字符串中具有可选参数,例如:

  • ~/api/products/filter?apc=AA&xpc=BB
  • ~/api/products/filter?sku=7199123

您可以使用以下方式:

[Route("products/filter/{apc?}/{xpc?}/{sku?}")]
public IHttpActionResult Get(string apc = null, string xpc = null, int? sku = null)
{ ... }

当这些类型已经有默认值时,为方法参数定义默认值似乎有点奇怪。


我赞同你的想法 - “当这些类型已经有默认值时,为方法参数定义默认值似乎很奇怪。” 我查看了MSDN上的详细信息,也在这里(https://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2#optional),但它没有讨论任何技术细节,为什么决定是这样的。 - RBT
43
可空性和可选性是两个不同的概念,它们之间没有任何关系(因为可空值可以在参数列表外使用)。简单地将参数声明为 int? 标记为可空,但它并非可选:你必须传递一个非空整数值或 null。然而,添加= null是声明可选参数默认值所需的语法。因此,int? sku = null 是一个可空的 int,其默认值为 null(而不是其他整数值)。 - Mike Hofer
@MikeHofer 我觉得你没有把你的精彩评论变成答案,可能失去了一些赞。就像《究竟是谁在说》(Whose Line is it Anyway?)一样,这不是我们来这里的原因吗? - ruffin
1
@ruffin 唉,你可能是正确的。但那个评论是5年前的了,得到那甜蜜的声望的机会可能早就过去了。 - Mike Hofer

39

你只需要为参数设置默认值(不需要使用Route属性):

public IHttpActionResult Get(string apc = null, string xpc = null, int? sku = null)
{ ... }

8

不推荐使用此解决方案,因为您需要提供额外的验证逻辑来检查参数是否实际上是一个“int”,如果它不是“null”。如果您坚持使用“int?”框架会提供开箱即用的验证,您只需要检查“ModelState”即可... - Bozhidar Stoyneff

2
[Route("~/api/[Controller]/AutocompleteAdress/{input=}/{input2=}")]
public IEnumerable<string> GetAutocompleteAdress(string input, string input2)

它对我有效(ASP.NET WEB API)。


这在我的使用中似乎效果很好。但是,你有这种语法的参考资料吗?此外,如果您不提供参数,它似乎会有点混乱默认的 ModelState。例如,我尝试使用 int orgId,当用户未提供时,ModelState 中同时具有 orgIdorgId.Int32。然而,{orgId:int=} 不起作用。 - Lovethenakedgun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接