使用 JQuery 1.9,我正在调用以下 ajax 语句:
var data =
{
PropertyId: 1912,
Position: 0,
Description: "State sales tax",
Rate: 5,
RateIsPercent: true
};
$.ajax(
{
type : "PUT",
url: "/api/taxes/5",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8"
});
在 Chrome 或 Firefox 中,我看到请求正文(字符串化数据)是有效的 JSON。它看起来像这样:
我已经使用其他解析器进行了验证,所有这些都确认这是有效的 JSON。
问题是这个 JSON 对象中的 PropertyId 成员没有绑定到 MVC 控制器方法中的对象属性,即使所有其他成员都绑定了。我收到以下错误:
{
"Message": "The request is invalid.",
"ModelState": {
"newTax.PropertyId": [
"The field PropertyId must be between 1 and 2147483647."
]
}
}
如上图所示,PropertyId 值为 1912。这显然是一个可接受的 int32 值。
那么为什么会抛出这个验证错误呢?
这是我希望它绑定到的对象:
public class Tax : CloneableObject
{
public Tax() { }
public int ID { get; set; }
[Required]
[Range(1, int.MaxValue)]
[IgnoreDataMember]
[Display(Name = "Property ID")]
public int PropertyId { get; set; }
[Required]
[Min(0)]
public int Position { get; set; }
[Required]
[StringLength(256)]
public string Description { get; set; }
[Required]
[DataType(DataType.Currency)]
public decimal Rate { get; set; }
[Required]
[Display(Name = "Rate Is Percent")]
public bool RateIsPercent { get; set; }
}
这是控制器中的操作方法:
// PUT: api/taxes/5
public Tax Put(int id, [FromBody]Tax newTax)
{
return TaxBusiness.Update(id, newTax).ExecuteOrThrow();
}
以下是配置的路由:
config.Routes.MapHttpRoute(name: "ApiPutPatchDelete", routeTemplate: "api/{controller}/{id}", defaults: null, constraints: new { httpMethod = new HttpMethodConstraint("PUT", "PATCH", "DELETE") });
config.Routes.MapHttpRoute(name: "ApiPost", routeTemplate: "api/{controller}", defaults: null, constraints: new { httpMethod = new HttpMethodConstraint("POST") });
config.Routes.MapHttpRoute(name: "ApiGet", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }, constraints: new { httpMethod = new HttpMethodConstraint("GET") });
我不相信它击中正确的路线有问题,因为如果我传递名称/值发布数据而不是 json,它就可以工作。例如,如果我改为调用它:
curl -X PUT http://app/api/taxes/5 -d "propertyId=1912&rate=50&etc..."
它工作得很好。
PropertyId 是唯一未正确绑定的成员。除了这个之外,没有其他验证错误。
我试过的...
如果我删除该[Range(1, int.MaxValue)]
属性,我不会收到任何验证错误,但 tax.PropertyId 最终的值为0
.
如果我从 PropertyId 中删除所有1912
属性,则该值完全可以通过.
同样,如果我使用名称/值发布字符串来发送如下值,这一切都不会发生:
"propertyId=1912&rate=23&etc...."
如果我这样做,所有验证都会按预期工作。这仅在我发布 json 字符串时发生。
更新:
它似乎与[IgnoreDataMember]
属性有关。如果我删除它,一切正常。如果我离开它,就会出现问题。
反序列化时是否[IgnoreDataMember]
跳过 json 对象成员?我以为[IgnoreDataMember]
只在序列化时使用,而不是反序列化。
如果是这样,是否有不同的方式告诉序列化忽略 PropertyId 字段,同时确保它在反序列化过程中被包含在内?