我试图阻止我的REST API在我的控制器中接受无效的json主体。
我有一个REST API,它有一个.NET MVC端点。在这个端点上,我们有一个post方法,它接受一个类型为customer的体(在本例中大大简化),它的类如下:
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Address> Addresses { get; set; }
public List<Xref> Xrefs { get; set; }
}
public class Address
{
public string AddressLineOne { get; set; }
public string AddressLineTwo { get; set; }
}
public class Xref
{
public string System { get; set; }
public List<Segment> Segments { get; set; }
}
public class Segment
{
public string Name { get; set; }
public string Value { get; set; }
}
控制器的方法如下:
[HttpPost]
public async Task<IHttpActionResult> Post([FromBody]Customer customer)
{
...
}
正文的有效json表示如下:
{
"FirstName": "firstName",
"LastName": "lastName",
"Addresses":
[
{
"AddressLineOne" : "addressLineOne",
"AddressLineTwo" : "addressLineTwo"
}
],
"Xrefs":[
{
"System":"systemOne",
"Segments":[
{
"Name":"name",
"Value":"value"
}
]
}
]
}
我注意到如果我使用无效的json向API发出请求,请求控制器仍然会收到正文,并且会在错误的部分之后忽略所有内容。此表示的一个示例位于外部参照没有右括号的位置:
{
"FirstName": "firstName",
"LastName": "lastName",
"Xrefs":[
{
"System":"systemOne",
"Segments":[
{
"Name":"name",
"Value":"value"
}
]
,
"Addresses":
[
{
"AddressLineOne" : "addressLineOne",
"AddressLineTwo" : "addressLineTwo"
}
],
}
将此数据发布到控制器时会发生的情况是客户对象将包含名字,姓氏和外部参照,但不包含地址。这是因为根据json层次结构,我们仍然在外部参照中并且没有将其关闭。
为此功能创建单元测试并尝试DeserializeObject时,会遇到JsonSerializationException,但这种情况不会发生在控制器方法中。
现在我正试图找到一种方法来阻止在控制器中接受无效的json。我不希望以任何形式进行部分json反序列化,json是有效还是不有效。我考虑构建验证过滤器并将其添加到HttpConfig,此过滤器将使用反射来找出请求的预期主体应该是什么样的,然后它会尝试将主体反序列化到其中,如果抛出异常请求不会通过。
我一直没有这么做,因为我认为有一种更简单,资源更少的方法来构建MVC,例如允许不完整的json体的标志,但我一直无法找到它。我也不愿意在过滤器中执行此操作,因为过滤每个请求会非常耗费资源,特别是因为反射非常繁琐而且我们正在捕获异常以尝试验证。这个过滤器在小型MVC API中可以正常使用,但该系统需要极低的响应时间。
如果您知道更好的解决方案,请告诉我们。
由于
答案 0 :(得分:0)
您应该能够使用模型绑定验证,只需在您的班级中添加关键字即可确保数据。
看一下使用一堆必需的标签:
public class Xref
{
[Required]
public string System { get; set; }
[Required]
public List<Segment> Segments { get; set; }
}
或一般验证模型:
[HttpPost]
[ValidateModel]
public async Task<IHttpActionResult> Post([FromBody]Customer customer)
{
...
}