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

Oli*_*pel 81 c# asp.net asp.net-web-api asp.net-web-api-routing

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

/v1/location/deviceid/appid

附加参数来自Post-Body.

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

/v1/location/deviceid
/v1/location/appid
/v1/location/
Run Code Online (Sandbox Code Playgroud)

这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);
}
Run Code Online (Sandbox Code Playgroud)

这不起作用并返回编译错误:

"可选参数必须在最后"

接下来尝试:

[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post([FromBody] location_fromuser BodyData, string deviceid = null, string appid = null)
Run Code Online (Sandbox Code Playgroud)

现在我的函数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)
Run Code Online (Sandbox Code Playgroud)

不工作:

BodyData不支持可选参数FormatterParameterBinding.

为什么我要一个带可选参数的解决方案?我的控制器只通过POST处理"添加新位置".

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

Kir*_*lla 161

对于传入的请求一样/v1/location/1234,你可以想像这将是困难的,如果对应于"1234"段的值与网络API自动弄清楚appid,而不是deviceid.

我认为您应该更改您的路由模板 [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")],然后解析deiveOrAppid以找出ID的类型.

此外,您还需要使路径模板中的段可选,否则段将被视为必需.请注意?这种情况下的字符.例如: [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]

  • 路由模板里面的`?`就是我想要的.+1 (45认同)
  • 仅供参考 - 当我们使用`?`字符在操作uri中将参数标记为可选时,我们必须为方法签名中的参数提供默认值,例如MyMethod(string name ="someDefaultValue",int?Id = null). (10认同)
  • 我不会说"deviceOrAppId"是最好的设计选择.我认为API应该始终根据定义知道它将尽可能地接收到什么. (4认同)

小智 44

另一个信息:如果你想使用Route Constraint,想象你想要强制该参数有int数据类型,那么你需要使用这个语法:

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

字符的最后一个前放总是}字符

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


RBT*_*RBT 16

将我的评论转换为答案以补充@Kiran Chala的答案,因为它似乎对观众有帮助 -

当我们使用?字符在操作uri中将参数标记为可选时,我们必须为方法签名中的参数提供默认值,如下所示:

MyMethod(string name = "someDefaultValue", int? Id = null)


Sha*_*dam 5

好的,我通过互联网研究陷入了困境,我继续我的方式,因为公认的解决方案不适用于 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>()));
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,许多路由都转到这个单一的 API 函数