2013-04-23 9 views
5

की बजाय असफल deserialization पर एक खाली वस्तु बनाता है WebAPI में, मैंने एक असाधारणता देखी है जो हमारे सत्यापन प्रथाओं के साथ गड़बड़ कर रहा है। यदि आप एक्सएमएल में एक पोस्ट के साथ एक खराब शरीर/पेलोड भेजते हैं, तो deserialization विफल रहता है और आप एक शून्य सूचक मिलता है। यदि आप JSON में खराब बॉडी/पेलोड भेजते हैं, तो आपको इसके बजाय एक खाली ऑब्जेक्ट मिलता है। यह भ्रामक है और मुझे यह पसंद नहीं है। एक असफल जेसन deserialization के साथ एक शून्य सूचक को मजबूर करने का कोई तरीका है ??JSON serializer शून्य

अद्यतन: मुझे एक deserialization समस्या नहीं है। मुझे एक व्यवहार समस्या है जो DataContractSerializer और Json.net serializer के बीच एक अंतर प्रतीत होता है। जब एक्सएमएल deserialize करने में विफल रहता है, पेलोड शून्य है। हालांकि, जब जेसन deserialize करने में विफल रहता है, ऐसा लगता है कि यह अपेक्षित पेलोड का एक डिफ़ॉल्ट उदाहरण तत्काल है। एक बुरा एक्सएमएल पेलोड के

उदाहरण: enter image description here

एक ही कॉल एक बुरा json पेलोड का उपयोग करने का उदाहरण

enter image description here

(। पेलोड नहीं अशक्त बजाय यह पेलोड वर्ग के एक डिफ़ॉल्ट उदाहरण है)
+1

आप कोड जो इस अंतर को दिखाया जा रहा है का हिस्सा हो सकता है? –

+0

मुझे यकीन नहीं है कि आपको कैसे दिखाया जाए क्योंकि यह प्रवेश बिंदु पर होता है। – Sinaesthetic

+1

ठीक है, स्टार्टर्स के लिए, अपना मॉडल दिखाएं, अपनी वेब एपीआई कंट्रोलर एक्शन दिखाएं जो इस मॉडल को तर्क के रूप में ले रहा है और एक्सएमएल और जेएसओएन को दिखा रहा है जो आप इस क्रिया में पोस्ट कर रहे हैं जो व्यवहार में आपके द्वारा देखे गए सटीक मतभेदों को समझाते हैं।यह एक रचनात्मक चर्चा शुरू करने के लिए पर्याप्त होना चाहिए जो इस प्रश्न के वर्तमान चरण में काफी कठिन है। –

उत्तर

4

डिफ़ॉल्ट रूप से Web.API ने JsonMediaTypeFormatter में MissingMemberHandling.Ignore सेटिंग का उपयोग किया।

आप के साथ MissingMemberHandling.Error के लिए यह निर्धारित करने की आवश्यकता:

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

और आप null जब की तरह JSON भेजने चाहिए: {} तो आप:

{ 
    "somenotexistingprop": "" 
} 

लेकिन यदि आप एक पूरी तरह से खाली JSON ऑब्जेक्ट भेज अभी भी रिक्त गुणों वाला ऑब्जेक्ट प्राप्त होगा और null नहीं होगा। क्योंकि JsonConvert.DeserializeObject एक खाली ऑब्जेक्ट देता है यदि यह एक खाली JSON deserializes (github का यह यूनिट परीक्षण देखें)।

+0

मुझे यह भी मिला। यह काम नहीं किया। वही परिणाम! – Sinaesthetic

+0

@ सिनेस्थेटिक मैंने अपने जवाब को हटा दिया है क्योंकि यह आपकी समस्या का समाधान है लेकिन वर्तमान में ऐसा लगता है कि वीपी.एपीआई में एक बग है जो इसे काम करने से रोकता है ... – nemesv

+1

मिसिंग मेम्बर को "त्रुटि" से जोड़ने के अलावा, आप भी कर सकते हैं निम्नलिखित जांच करें ताकि एक्सएमएल और जेसन फॉर्मेटर्स में यह लगातार संगत हो सके, अगर (! ModelState.IsValid) { नया HttpResponseException फेंक दें (Request.CreateErrorResponse (HttpStatusCode.BadRequest, this.ModelState)); } ' –

1

मेरी टीम के सदस्यों में से एक के बाद मुझे समझ में क्यों यह मामला है, तो निम्न इस परिदृश्य के बारे में कुछ नोट कर रहे हैं मदद की:

  1. हम डिफ़ॉल्ट रूप से "MissingMemberHandling.Error" की जरूरत नहीं है Json फ़ॉर्मेटर पर इस वजह उन परिदृश्यों में सहायता कर सकते हैं जहां आप क्लाइंट का एक नया संस्करण सेवा के पुराने संस्करण में अतिरिक्त सदस्यों के साथ डेटा भेज रहे हैं। सेवा का पुराना संस्करण अभी भी इस अनुरोध को स्वीकार करने और अतिरिक्त गुणों को अनदेखा करने में सक्षम होना चाहिए। यह व्यवहार इस बात के अनुरूप है कि एक्सएमएल फॉर्मेटर कैसे व्यवहार करता है।

  2. @ सिनेस्थेटिक: यदि आप "मिसिंगमम्बरहैंडलिंग.इरर" सेट कर रहे हैं और केवल "ModelState.IsValid" पर भरोसा नहीं करना चाहते हैं, तो आप यह पता लगाने के लिए मॉडलस्टेट की कुंजी प्रॉपर्टी की जांच कर सकते हैं कि आपका अनुरोध वास्तव में अमान्य है या नहीं एक लापता सदस्य या कुछ और के कारण।

उदाहरण नीचे:

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 
    } 
संबंधित मुद्दे