2

使用 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 字段,同时确保它在反序列化过程中被包含在内?

4

2 回答 2

1

根据我的阅读,没有办法使用属性来停止序列化而不是反序列化。 IgnoreDataMember两者JsonIgnore都做同样的事情。

我让它工作的ShouldSerialize方法是完全删除属性并切换到条件序列化方法。

ShouldSerialize 上的 Json.NET 文档

于 2013-04-22T11:30:31.827 回答
0

在属性 PropertyId

[Required]
[Range(1, int.MaxValue)]
[IgnoreDataMember]
[Display(Name = "Property ID")]
public int PropertyId { get; set; }

我认为问题是属性 [IgnoreDataMember]。您尝试使用 attr [JsonIgnore] 而不是 [IgnoreDataMember]。请参见下面的代码:

[Required]
[Range(1, int.MaxValue)]
[JsonIgnore]
[Display(Name = "Property ID")]
public int PropertyId { get; set; }

不要忘记添加参考 Newtonsoft.Json 和

using Newtonsoft.Json;

在你的代码中。

希望有用!

于 2013-04-22T04:06:44.517 回答