【发布时间】:2013-02-28 18:18:11
【问题描述】:
我有以下型号:
public class Resource
{
[DataMember(IsRequired = true)]
[Required]
public bool IsPublic { get; set; }
[DataMember(IsRequired = true)]
[Required]
public ResourceKey ResourceKey { get; set; }
}
public class ResourceKey
{
[StringLength(50, MinimumLength = 1)]
[Required]
public string SystemId { get; set; }
[StringLength(50, MinimumLength = 1)]
[Required]
public string SystemDataIdType { get; set; }
[StringLength(50, MinimumLength = 1)]
[Required]
public string SystemEntityType { get; set; }
[StringLength(50, MinimumLength = 1)]
[Required]
public string SystemDataId { get; set; }
}
我有以下动作方法签名:
public HttpResponseMessage PostResource(Resource resource)
我在正文中使用 JSON 发送以下请求(属性“IsPublic”的故意无效值):
Request Method:POST
Host: localhost:63307
Connection: keep-alive
Content-Length: 477
User-Agent: Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.97 Safari/537.22
Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
{
"IsPublic": invalidvalue,
"ResourceKey":{
"SystemId": "asdf",
"SystemDataIdType": "int",
"SystemDataId": "Lorem ipsum",
"SystemEntityType":"EntityType"
},
}
这是无效的 JSON - 通过 JSONLint 运行它,它会告诉你:
第 2 行解析错误:
{ "IsPublic": 无效值,
..................^ 期望 'STRING'、'NUMBER'、'NULL'、'TRUE'、'FALSE'、'{'、'['
ModelState.IsValid 属性为 'true' - 为什么???
此外,格式化程序似乎放弃了反序列化并简单地将“资源”参数作为 null 传递给操作方法,而不是引发验证错误!
请注意,如果我为其他属性输入无效值也会发生这种情况,例如替换:
"SystemId": notAnObjectOrLiteralOrArray
但是,如果我发送以下 JSON 并为“SystemId”属性发送一个特殊的 undefined 值:
{
"IsPublic": true,
ResourceKey:{
"SystemId": undefined,
"SystemDataIdType": "int",
"SystemDataId": "Lorem ipsum",
"SystemEntityType":"EntityType"
},
}
然后我得到以下合理的异常抛出:
Exception Type: Newtonsoft.Json.JsonReaderException
Message: "Error reading string. Unexpected token: Undefined. Path 'ResourceKey.SystemId', line 4, position 24."
Stack Trace: " at Newtonsoft.Json.JsonReader.ReadAsStringInternal()
at Newtonsoft.Json.JsonTextReader.ReadAsString()
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)"
SO:Newtonsoft.Json 库中发生了什么,导致看起来像部分 JSON 验证???
PS:可以将 JSON 名称/值对发布到 Web API,而无需将名称括在引号中...
{
IsPublic: true,
ResourceKey:{
SystemId: "123",
SystemDataIdType: "int",
SystemDataId: "Lorem ipsum",
SystemEntityType:"EntityType"
},
}
这也是无效的 JSON!
【问题讨论】:
-
我能够通过一个大大简化的示例来复制这个问题 - pastebin.com/ehDgWQBu - 输出是:200 - OK - 400 - BadRequest - {"Message":"Model data is null,但它并没有通过验证!”} 我最近在另一个项目中遇到了这个问题,并认为它是我当时正在使用的自定义媒体类型格式化程序的奇怪之处,但这个示例仅使用标准格式化程序并展示了这个问题,所以我很好奇这一切意味着什么......
-
我认为这个谜语的答案在默认模型绑定或参数绑定配置中,甚至可能在媒体类型格式化程序 (
JsonMediaTypeFormatter) 中。