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

本文关键字:参数 API 属性 路由 Web | 更新日期: 2023-09-27 17:55:32

我想处理以下API调用的POST:

/v1/location/deviceid/appid

附加参数来自后正文。

这一切对我来说都很好。现在我想通过允许"deviceid"和/或"appid"和/或BodyData为空来扩展我的代码:

/v1/location/deviceid
/v1/location/appid
/v1/location/

这 3 个 URL 应由相同的路由响应。

我的第一个方法(需要身体数据):

[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 - 即使调用发送了 Body。

最后我设置所有 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 处理"添加新位置"。

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

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

对于像 /v1/location/1234 这样的传入请求,可以想象,Web API 很难自动确定对应于 '1234' 的段的值是否与appid相关,而不是与deviceid有关。

我认为您应该将路线模板更改为类似 [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")],然后分析deiveOrAppid以确定 id 的类型。

此外,您需要将路由模板本身中的分段设置为可选,否则这些分段将被视为必需的。请注意本例中的?字符。例如: [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]

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

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

字符始终放在最后一个 } 字符之前

有关详细信息,请参阅:可选 URI 参数和默认值

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

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

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

好的,我在这里进行了互联网研究,我继续我的方式,因为公认的解决方案不适用于 dotnet core 3.1。所以这是我的解决方案,按照这个文档

[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 函数