ChatGPT解决这个技术问题 Extra ChatGPT

Web Api 属性路由中的可选参数

我想处理以下 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 处理“添加新位置”。

我想发送我自己的异常或错误消息的错误数据。即使调用有缺失值。在这种情况下,我希望能够决定通过我的代码抛出异常或设置默认值。


T
Thomas Eyde

对于像 /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,我被难住了一分钟。谢谢!
凉爽的。很高兴它对您有所帮助@sm 我已将我的评论转换为答案以获得更好的可见性,因为它似乎很有帮助。这将是 Kiran 帖子的附加内容。
a
abatishchev

另一个信息:如果你想使用路由约束,假设你想强制参数具有 int 数据类型,那么你需要使用这个语法:

[Route("v1/location/**{deviceOrAppid:int?}**", Name = "AddNewLocation")]

这 ?字符总是放在最后一个 } 字符之前

有关详细信息,请参阅:Optional URI Parameters and Default Values


R
RBT

补充@Kiran Chala的答案的另一个事实-

当我们使用 ? 字符(对于 nullable value types)在操作 URI 中将任何参数(id)标记为可选时,我们必须为方法签名中的参数提供默认值,如下所示:

[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post(string name, int? Id = null)

我正要发表同样的评论。
正是我的问题。我记得路由中的问号,但忘记了方法参数中的默认值。
S
Shadam

好的,我的互联网研究落到了这里,我继续我的方式,因为公认的解决方案不适用于 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 仍然将其标记为必填,并且不会让它在没有值的情况下提交

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅