2011-08-30 12 views
7

मुझे हाल ही में किसी ग्राहक के लिए JSON समाधान लागू करते समय एक समस्या का सामना करना पड़ा। यदि कार्रवाई पैरामीटर नाम मॉडल के किसी संपत्ति नाम से मेल खाता है, तो बाइंडर किसी भी गुण को बाध्य करने में विफल रहता है।एमवीसी 3 जेसन बाइंड बग?

एक उदाहरण:

नियंत्रक लोग

public ActionResult SetEmails(Person emails){ 
    ... 
    return Content(""); 
} 

क्योंकि पैरामीटर नाम, "ईमेल" कहा जाता था और उस व्यक्ति मॉडल "ईमेल" .. बांधने की मशीन में विफल रहता है कहा जाता है की एक संपत्ति नाम से मेल खाता है, लेकिन .. क्यों के रूप में कोई संकेत नहीं देता

वे था एक मॉडल व्यक्ति

public class Person { 
    public string Name { get; set; } 
    public List<string> Emails { get; set; } 

    public Person() { 
     Emails = new List<string>(); 
    } 
} 
बुलाया

क्या यह एक बग है, या 'फीचर' है?

बस एक साइड नोट के रूप में, मेरा प्रश्न इस बात के संबंध में अधिक है कि एक तर्क नाम बाइंडर के साथ संघर्ष कैसे कर सकता है? नाम से कोई फर्क नहीं पड़ता क्योंकि यह वर्ग प्रकार है जो जेसन डेटा के खिलाफ मिलान करने के लिए इसकी स्कीमा को परिभाषित करता है .. बाइंडर को क्यों तर्क देना चाहिए कि आप तर्क का नाम क्या हैं या यदि यह तर्क के वर्ग प्रकार के भीतर किसी संपत्ति के नाम से मेल खाता है?

+4

क्या आप कॉलिंग जेएस कोड पोस्ट कर सकते हैं, या कम से कम जेएसओएन जो आप सबमिट कर रहे हैं? –

+0

जेसन होगा: {"नाम": "जॉन", "ईमेल": ["[email protected]", "test2 @ test।कॉम "]} जेसन ठीक था, जैसा कि मैंने कहा था, एक बार मैंने ईमेल से क्रिया तर्क नाम बदल दिया (मॉडल संपत्ति नाम से मेल खाता है) जो मेल नहीं खाता था, यह काम करता था .. मैंने सोचा कि यह दिलचस्प था और यह नहीं देख सकता कि यह क्यों काम नहीं करना चाहिए, या कम से कम तत्काल वर्ग के बदले एक अपरिपक्व वर्ग के बदले अपवाद फेंकना चाहिए! – Mike

उत्तर

2

समस्या यह है कि आपके शब्दकोश में एक अस्पष्टता है, जिसमें दो तत्व "ईमेल" नाम दिए गए हैं (हालांकि अलग-अलग आवरण के साथ)। DefaultModelBinder इस अस्पष्टता को हल नहीं कर सकता है।

दो संभावित समाधान: (1) यदि आप एक संपूर्ण व्यक्ति मॉडल को पारित कर रहे हैं, तो अपने शीर्ष-स्तर तत्व का नाम "व्यक्ति" (जिसे संदर्भ में अधिक समझ में आता है) में बदलें, जो अस्पष्टता को हटा देगा , और बाइंडिंग को अपेक्षित होने की अनुमति दें, या (2) यदि आप ईमेल की एक सूची वापस भेज रहे हैं, तो अपने क्रिया हस्ताक्षर को public ActionResult SetEmails(List<Emails> emails) पर बदलें।

मैं आपको किसी भी बग या फीचर का अनुभव नहीं करता हूं, लेकिन आपके डिज़ाइन के साथ कोई समस्या है।

+0

मैंने इसे व्यक्ति को बदल दिया, जिसने इस मुद्दे को हल किया। नाम एक आवश्यकता नहीं है, मैं सिर्फ विरासत कोड और मेरा आखिरी विचार ले रहा था कि क्यों मॉडल बाइंडर असफल हो गया था कि कार्रवाई तर्क नाम तर्क वर्ग प्रकार के संपत्ति नाम से मेल खाता था। मुझे नहीं पता कि इससे कोई अस्पष्टता क्यों होगी? ईमेल .GetType()। GetProperties() इत्यादि .. उनसे जेसन आने के खिलाफ मैच करें .. यदि कोई तर्क वर्ग प्रकार (स्कीमा मुझे लगता है) जेसन के महान से मेल खाता है, तो महान .. तर्क क्या है ई बात है? बाध्यकारी के दौरान नाम कैसे खेलता है? इसका नाम इसके वर्ग के प्रकार को निर्देशित नहीं करता है! – Mike

+0

JSON 'DictionaryValueProvider' के माध्यम से बाध्य है, इसलिए मान कुंजी नामों के माध्यम से जुड़े हुए हैं। यदि एक ही नाम की दो कुंजी हैं, तो शब्दकोश मान्य नहीं होगा। अगर यह मददगार था तो कृपया उत्तर के रूप में चिह्नित करें। – counsellorben

+1

और उन चाबियों को वर्ग गुणों से आना चाहिए, न कि उस नाम को जिसे आपने तर्क दिया है जिसका उपयोग आपके मॉडल को बांधने के लिए किया जाता है। पैरामीटर नाम की इसकी प्रासंगिकताओं पर पुनरावृत्ति होने पर कोई प्रासंगिकता कैसे होती है? var pi = controller.GetMethod ("action")। GetParameters(); यहां, आपको पैरामीटर के नाम की आवश्यकता होती है या पैरामीटर को पुनर्प्राप्त करने के नतीजे पर यह कैसे प्रभाव डालता है, इस बिंदु पर आप डेटा के प्रकार को प्राप्त करने के लिए इसके वर्ग के प्रकार को फिर से प्राप्त कर सकते हैं और इसके गुणों पर पुनरावृत्ति कर सकते हैं। यह दो गुणों का एक प्रश्न नहीं है (अमान्य और संकलित नहीं होगा) .. – Mike

0

मैं यह नहीं कह रहा हूं कि उत्तर के लिए यह है, लेकिन आप अपनी संपत्ति का नाम बदलने से बच सकते हैं।

पैरामीटर के परिवर्तनीय नाम के साथ अपने JSON ऑब्जेक्ट को लपेटें (इस मामले में, यह "ईमेल" है)। तो यह काम करता है:

डेटा: JSON.stringify ({ईमेल: {नाम: "मेरा नाम", ईमेल: [ "[email protected]", "[email protected]"]}}) ;

लेकिन यह नहीं है - modelbinder रिटर्न के बजाय शून्य:

डेटा: JSON.stringify ({नाम: "मेरा नाम", ईमेल: [ "[email protected]" " [email protected] "]});

फिर भी, यह बहुत क्रोधित है। हालांकि चीजें कवर के तहत गहरी काम करती हैं, मेरे वेब क्लाइंट को यह जानना नहीं चाहिए कि कंट्रोलर में पैरामीटर नाम सही तरीके से काम करने के लिए क्या है। जहां तक ​​मेरा संबंध है, यह एमवीसी के मॉडलबिंडर में एक बग है।