2013-04-23 16 views
5

WebAPIでは、私たちの検証方法が矛盾していることに気付きました。あなたがxmlのPOSTで悪いボディ/ペイロードを送ると、デシリアライゼーションは失敗し、あなたはヌルポインタを取得します。 JSONでボディ/ペイロードを送信すると、代わりに空のオブジェクトが取得されます。それは誤解を招き、私はそれを好まない。失敗したjsonのデシリアライゼーションでヌルポインタを強制する方法はありますか?JSONシリアライザは、nullの代わりにデシリアライゼーションが失敗した場合に空のオブジェクトを作成します。

更新: デシリアライズの問題はありません。私は、DataContractSerializerとJson.netシリアライザの違いと思われる動作上の問題を抱えています。 xmlが逆直列化に失敗した場合、ペイロードはヌルです。しかし、Jsonがデシリアライズに失敗した場合、期待されるペイロードのデフォルトインスタンスをインスタンス化しているようです。悪いJSONペイロードを使用して、同じコールの enter image description here

例(ペイロードがnullでない代わりに、それはペイロードクラスの既定のインスタンスである。)

enter image description here

悪いXMLペイロードの例

+1

あなたはこの違いを見せているコードを共有するだろうか? –

+0

私はあなたがエントリーポイントで起こるようにあなたを見せる方法がわかりません。 – Sinaesthetic

+1

まず、モデルを表示し、このモデルを引数とするWeb APIコントローラーのアクションを表示し、このアクションに投稿しているXMLとJSONを表示して、ビヘイビアーで実際に観察した違いを説明してください。これは、この質問の現段階ではかなり困難な建設的な議論を開始するのに十分なはずです。 –

答えて

4

デフォルトでWeb.APIはのMissingMemberHandling.Ignore設定を使用しました。

あなたはとMissingMemberHandling.Errorに設定する必要があります。

GlobalConfiguration.Configuration 
    .Formatters.JsonFormatter 
    .SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error; 

などJSONを送信するときに、あなたはnullを取得する必要があります:あなたは{}次のようにします。しかし

{ 
    "somenotexistingprop": "" 
} 

あなたが完全に空のJSONオブジェクトを送信する場合nullではなく、空のプロパティを持つオブジェクトを取得します。 JsonConvert.DeserializeObjectは、空のJSONを逆シリアル化する場合は空のオブジェクトを返します(このユニットテストgithubを参照)。

+0

私はこれも見つけました。それはうまくいかなかった。同じ結果! – Sinaesthetic

+0

@Sinaestheticこれはあなたの問題の解決策であるため、私は自分の答えを元に戻しましたが、現在はWep.APIにバグがあるようです。 – nemesv

+1

MissingMemberHandlingを "Error"にする以外にも、次のチェックを行い、XmlおよびJsonフォーマッタ間で一貫性があるようにします。if(!ModelState.IsValid) { 新しいHttpResponseExceptionをスローします(Request.CreateErrorResponse(HttpStatusCode.BadRequest、this.ModelState))); } ' –

1

私のチームのメンバーの一人は、このような場合は、なぜ私が理解して助けた後、次はこのシナリオに関するいくつかの注意事項です。このため、

  1. 我々は、デフォルトでは、JSONのフォーマッタの「MissingMemberHandling.Error」を持っていません余分なメンバーを持つデータを古いバージョンのサービスに送信する新しいバージョンのクライアントがある場合に役立ちます。古いバージョンのサービスでは、依然としてこの要求を受け入れ、余分なプロパティを無視することができます。この動作は、XMLフォーマッタの動作と一貫しています。

  2. @Sinaesthetic: "MissingMemberHandling.Error"を設定していて、 "ModelState.IsValid"チェックにのみ依存したくない場合は、ModelStateのKeysプロパティを確認して、リクエストが本当に無効かどうかを調べることができます不足しているメンバーや何か他の人のために。

以下の例:

public class Customer 
{ 
    public int Id { get; set; } 

    [MaxLength(5)] 
    public string Name { get; set; } 

    public Address Address { get; set; } 
} 

public class Address 
{ 
    public string Line1 { get;set;} 
} 

//action 
public void Post([FromBody]Customer customer) 
    { 
     if (!ModelState.IsValid) 
     { 
      ModelStateDictionary msd = new ModelStateDictionary(); 

      foreach (string key in ModelState.Keys) 
      { 
       if (ModelState[key].Errors.Count > 0) 
       { 
        foreach (ModelError error in ModelState[key].Errors) 
        { 
         Exception ex = error.Exception; 

         if (ex != null 
          && typeof(JsonSerializationException).IsAssignableFrom(ex.GetType()) 
          && ex.Message.StartsWith("Could not find member")) 
         { 
          msd.AddModelError(key, ex); 
         } 
        } 
       } 
      } 

      if (msd.Count > 0) 
      { 
       throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, msd)); 
      } 
     } 

     //process the supplied customer 
    } 
関連する問題