【问题标题】:.NET MVC controller accepting invalid json.NET MVC 控制器接受无效的 json
【发布时间】:2017-06-23 13:04:56
【问题描述】:

我试图阻止我的 REST API 在我的控制器中接受无效的 json 正文。

我有一个带有 .NET MVC 端点的 REST API。在这个端点上,我们有一个 post 方法,它接受一个客户类型的主体(在这个例子中大大简化了),它的类如下:

 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 中会很好,但此系统需要极短的响应时间。

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

谢谢

【问题讨论】:

  • 使用 Json Schema,见newtonsoft.com/jsonschema
  • 和一个自定义模型绑定器,您可以在其中验证 JSON
  • 或使用字符串客户...您将获得JSON字符串,验证并将json转换为所需的对象。

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


【解决方案1】:

您应该能够使用模型绑定验证来确保数据,只需向您的类添加关键字。

看看使用一堆必需的标签:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-01
    相关资源
    最近更新 更多