.NET MVC控制器接受无效的json

时间:2017-02-06 14:36:41

标签: c# asp.net-mvc asp.net-mvc-4 asp.net-web-api asp.net-mvc-5

我试图阻止我的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中可以正常使用,但该系统需要极低的响应时间。

如果您知道更好的解决方案,请告诉我们。

由于

1 个答案:

答案 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)
{
...
}

See this for specific examples