Web Api 属性路由中的可选参数
Posted
技术标签:
【中文标题】Web Api 属性路由中的可选参数【英文标题】:Optional Parameters in Web Api Attribute Routing 【发布时间】:2014-05-11 19:11:12 【问题描述】:我想处理以下 API-Call 的 POST:
/v1/location/deviceid/appid
附加参数来自 Post-Body。
这一切对我来说都很好。现在我想通过允许“deviceid”和/或“appid”和/或 BodyData 为空来扩展我的代码:
/v1/location/deviceid
/v1/location/appid
/v1/location/
这 3 个 URL 应该由相同的路由响应。
我的第一种方法(需要 BodyData):
[Route("v1/location/deviceid/appid", Name = "AddNewLocation")]
public location_fromuser Post(string deviceid = null, string appid = null, [FromBody] location_fromuser BodyData)
return repository.AddNewLocation(deviceid, appid, BodyData);
这不起作用并返回编译错误:
"可选参数必须在末尾"
下一次尝试:
[Route("v1/location/deviceid/appid", Name = "AddNewLocation")]
public location_fromuser Post([FromBody] location_fromuser BodyData, string deviceid = null, string appid = null)
现在我的函数 AddNewLocation() 总是得到一个 BodyData=null
- 即使调用发送正文。
最后我将所有 3 参数设置为可选:
[Route("v1/location/deviceid/appid", Name = "AddNewLocation")]
public location_fromuser Post(string deviceid = null, string appid = null, [FromBody location_fromuser BodyData = null)
不工作:
FormatterParameterBinding
不支持可选参数BodyData
。
为什么我需要带有可选参数的解决方案?我的控制器仅通过 POST 处理“添加新位置”。
我想发送我自己的异常或错误消息的错误数据。即使调用有缺失值。在这种情况下,我希望能够决定通过我的代码抛出异常或设置默认值。
【问题讨论】:
【参考方案1】:对于像/v1/location/1234
这样的传入请求,您可以想象,Web API 很难自动确定与“1234”对应的段的值是否与appid
相关而不是与deviceid
相关.
我认为您应该将路线模板更改为
[Route("v1/location/deviceOrAppid?", Name = "AddNewLocation")]
然后解析deiveOrAppid
来找出id的类型。
您还需要将路线模板本身中的路段设为可选,否则路段将被视为必需。请注意本例中的 ?
字符。
例如:
[Route("v1/location/deviceOrAppid?", Name = "AddNewLocation")]
【讨论】:
?
在路由模板中是我正在寻找的。 +1
我不会说“deviceOrAppId”是最好的设计选择。我认为如果可能的话,API 应该总是知道它会收到什么。
仅供参考 - 当我们在操作 uri 中使用 ?
字符将参数标记为可选时,我们必须为方法签名中的参数提供默认值,例如MyMethod(string name = "someDefaultValue", int?Id = null).
@RBT 你是真正的 MVP,我被难住了一分钟。谢谢!
酷。很高兴它帮助了你@s.m。我已将我的评论转换为答案以获得更好的可见性,因为它似乎很有帮助。这将是 Kiran 帖子的附加内容。【参考方案2】:
另一个信息:如果您想使用 Route Constraint,假设您想强制该参数具有 int 数据类型,那么您需要使用以下语法:
[Route("v1/location/**deviceOrAppid:int?**", Name = "AddNewLocation")]
? 字符总是放在最后一个 字符之前
欲了解更多信息,请参阅:Optional URI Parameters and Default Values
【讨论】:
【参考方案3】:补充@Kiran Chala 回答的另一个事实 -
当我们在操作 URI 中使用?
字符(对于nullable value types)将任何参数(id
)标记为可选时,我们必须为方法签名中的参数提供默认值,如下所示:
[Route("v1/location/deviceid/appid", Name = "AddNewLocation")]
public location_fromuser Post(string name, int? Id = null)
【讨论】:
我正要发表同样的评论。【参考方案4】:好的,我的互联网研究落到了这里,我继续我的方式,因为公认的解决方案不适用于 dotnet core 3.1。 所以这是我的解决方案,遵循this doc
[HttpPost]
[Route("name")]
[Route("name/parent/parentId")]
public async Task<IActionResult> PostSomething(string name, Guid? parentId = null)
return Ok(await Task.FromResult(new List<string>()));
通过这种方式,许多路由都转到了这个单一的 API 函数
【讨论】:
我以为你在做某事,但对我来说,这是在大摇大摆地生成两个端点,而且两者都是必需的。 :// 好的。也许它的招摇。我现在在我的方法中只有 [HttpPost("~/Path/Action/paramName?")] 和一个可为空的 int ,没有默认值,并且从邮递员那里可以正常工作。 Swagger 一直在将我所有的尝试都标记为必要的。现在如何修复招摇? @johnw182 如果您希望参数不是必需的,则需要设置默认值,因为如果您不想大摇大摆地希望您提供该值,但可以使用默认值。 对于生成的两个端点,这很正常,您设置了两个路由,因此两个端点可用:) 我做了默认。 Swagger 仍然将其标记为必填,并且不会让它在没有值的情况下提交以上是关于Web Api 属性路由中的可选参数的主要内容,如果未能解决你的问题,请参考以下文章