TL; DR:不要使用[FromBody],但要滚动使用自己的版本,并具有更好的错误处理能力。原因如下。
其他答案描述了此问题的许多可能原因。但是,根本原因是[FromBody]
简单的错误处理非常糟糕,这使其在生产代码中几乎毫无用处。
例如,参数成为的最典型原因之一null
是请求正文具有无效的语法(例如,无效的JSON)。在这种情况下,将返回一个合理的API 400 BAD REQUEST
,并且一个合理的Web框架将自动执行此操作。但是,ASP.NET Web API在这方面是不合理的。只需将参数设置为null
,然后请求处理程序就需要“手动”代码来检查参数是否为null
。
因此,此处给出的许多答案在错误处理方面是不完整的,并且有缺陷的或恶意的客户端可能会通过发送无效的请求而导致服务器端发生意外行为,这将(最好)在NullReferenceException
某个地方抛出错误并返回不正确的请求状态500 INTERNAL SERVER ERROR
或者更糟的是,做意外的事情,崩溃或暴露安全漏洞。
适当的解决方案是编写一个自定义的“ [FromBody]
”属性,该属性会进行正确的错误处理并返回正确的状态代码,最好带有一些诊断信息以帮助客户开发人员。
可能有帮助(尚未测试)的解决方案是使参数成为必需,如下所示:https : //stackoverflow.com/a/19322688/2279059
以下笨拙的解决方案也适用:
public HttpResponseMessage MyAction([FromBody] JObject json)
{
if (json == null) {
var response = new HttpResponseMessage(HttpStatusCode.BadRequest) {
ReasonPhrase = "Invalid JSON"
};
throw new HttpResponseException(response);
}
MyParameterModel param;
try {
param = json.ToObject<MyParameterModel>();
}
catch (JsonException e) {
var response = new HttpResponseMessage(HttpStatusCode.BadRequest) {
ReasonPhrase = String.Format("Invalid parameter: {0}", e.Message)
};
throw new HttpResponseException(response);
}
}
这确实(希望)进行了正确的错误处理,但声明性较差。例如,如果使用Swagger记录您的API,则它将不知道参数类型,这意味着您需要找到一些手动解决方法来记录您的参数。这只是为了说明[FromBody]
应。
编辑:一个不太笨拙的解决方案是检查ModelState
:https : //stackoverflow.com/a/38515689/2279059
编辑:似乎ModelState.IsValid
没有像人们期望的那样设置为,false
如果使用JsonProperty
withRequired = Required.Always
且缺少参数。所以这也是没有用的。
但是,我认为,任何需要在每个请求处理程序中编写其他代码的解决方案都是不可接受的。在具有强大序列化功能的.NET语言和ASP.NET Web API这样的框架中,请求验证应该是自动的并且是内置的,即使Microsoft没有提供必要的内置功能,也完全可以执行工具。