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フィールドを無視するようにシリアル化に指示する別の方法はありますか?