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


89

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

/v1/location/deviceid/appid

附加参数来自后机构。

这一切对我来说都很好。现在,我通过允许将“ deviceid”和/或“ appid”和/或BodyData设置为null来扩展代码:

/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)

现在BodyData=null,即使调用发送了Body,我的函数AddNewLocation()也总是得到-。

最后,我将所有3个参数设置为可选:

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

不工作:

BodyData不支持可选参数FormatterParameterBinding

为什么要使用可选参数的解决方案?我的控制器仅通过POST处理“添加新位置”。

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

Answers:


174

对于传入的请求一样/v1/location/1234,你可以想像这将是困难的Web API自动计算出,如果对应于“1234”段的值与appid和不deviceid

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

另外,您还需要使路由模板本身中的线段为可选,否则将根据需要将线段视为。?在这种情况下,请注意字符。例如: [Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]


55
?我一直在寻找路由模板中的内容。+1
Kal_Torak

4
我不会说“ deviceOrAppId”是最佳设计选择。我认为API应该始终通过定义知道如果可能的话它将接收什么。
Niels Brinch

13
仅供参考-当在操作uri中使用?字符将参数标记为可选参数时,我们必须在方法签名中为参数提供默认值,例如MyMethod(字符串名称=“ someDefaultValue”,int?Id = null)。
RBT

@RBT,您是真正的MVP,我在那里呆了一分钟。谢谢!
SM

1
凉。很高兴为您提供了@sm,因为它似乎很有帮助,所以我已将我的评论转换为一个更好的可见性的答案。这将是Kiran帖子的附加内容。
RBT

45

另一个信息:如果要使用Route Constraint,想象一下要强制该参数具有int数据类型,则需要使用以下语法:

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

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

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


18

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

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

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


我也要发表同样的评论。
Jnr
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.