2013-02-19 74 views
16

एक मौजूदा प्रोजेक्ट में क्लाइंट ने दो तरीकों से प्रश्नावली का जवाब देने की संभावना मांगी: एक Wizard (एक समय में एक प्रश्न) और Listing (एक ही समय में सभी प्रश्न) का उपयोग करके प्रपत्र। दोनों तरीकों को पहले ही लागू कर दिया गया है।क्यों एएसपी.नेट एमवीसी डिफ़ॉल्ट मॉडल बाइंडर धीमा है? अपने काम को करने में काफी समय लग रहा है

प्रश्न AJAX का उपयोग कर मैनुअल के अध्याय में डेटाबेस से लोड किए गए हैं (यह बहुत तेज़ है)। इस समय सबसे बड़ा अध्याय 230 प्रश्न है (प्रत्येक 4 HTML इनपुट फ़ील्ड के साथ - इनपुट/टेक्स्ट, चयन, आदि)। यदि उपयोगकर्ता Listing प्रारूप में उत्तर देने के लिए ऐसे अध्याय का चयन करता है, तो <form> में सर्वर पर पोस्ट करने के लिए लगभग 920 फ़ील्ड होंगे।

data: $("#questions :input").serialize() 

यह क्रमबद्धता 207.143ms लेता है पूरा करने के लिए:

मैं एक AJAX पोस्ट अनुरोध jQuery के serialize विधि के साथ डेटा गुजर कर रहा हूँ।

console.profile(); 
$("#questions :input").serialize(); 
console.profileEnd(); 

फिर इस सुपर तेज है ...

समस्या आता है जब हाइड्रेटिंग डेटा निम्नलिखित कार्रवाई विधि पर प्राप्त:

public async Task<ActionResult> ListSaveAsync(IEnumerable<AnswerViewModel> questions) 

मैं Firefox में Firebug के साथ इस मूल्य डिबगिंग मिला जैसा कि आप देखते हैं, पोस्ट किया गया डेटा डेटा IEnumerable<AnswerViewModel> questions से जुड़ा हुआ है। AnswerViewModel में प्रत्येक उत्तर को स्टोर करने के लिए केवल 4 फ़ील्ड हैं।

बात यह है कि यह इस कार्रवाई विधि पर एक ब्रेकपाइंट हिट करने के लिए सहेजें बटन क्लिक करने के बाद समय की एक पर्याप्त राशि (ठीक 10 सेकंड) लेता है, वह है, उन 10 सेकंड मॉडल बांधने की मशीन में शायद खर्च हो रहा है है।

उल्लेख करने के लिए एक महत्वपूर्ण बात यह है कि मैं स्टीव सैंडर्सन के @Html.BeginCollectionItem helper का उपयोग कर रहा हूं ताकि HTTP पोस्ट से व्यूमोडेल संग्रह गुणों को पूरा करने में सहायता मिल सके। कैसे डेटा ViewModel (कुंजी) में हो जाता है देखें:

enter image description here

आप जानते हैं कि मैं इस अनुकूलन करने के लिए क्या करने की कोशिश कर सकते हैं करते हैं?

  1. सहेजें वापस केवल संशोधित सवाल:

    मैं लगभग 4 समाधान सोचा। ऐसा करने के लिए मुझे लिस्टिंग लोड करते समय डेटा-एट्रिब्यूट में प्रत्येक उत्तर मान को स्टोर करने की आवश्यकता होगी और <form> सबमिट करते समय वास्तविक मान के साथ इसकी तुलना करें क्योंकि यह व्यक्ति here सुझाता है।

  2. क्लाइंट पक्ष पर AnswerViewModel जावास्क्रिप्ट ऑब्जेक्ट बनाएं और उन्हें क्रिया विधि में पास करें। क्या यह मॉडल बाइंडर को कम करेगा?

  3. अपना खुद का मॉडल बाइंडर रोल करें ... लेकिन मुझे सच में नहीं पता कि यह एएसपी.नेट एमवीसी के साथ आने वाले डिफ़ॉल्ट से तेज होगा या नहीं। जो मैंने पढ़ा है, उससे डिफ़ॉल्ट मॉडल बाइंडर मान सेट करने के लिए बहुत सारे प्रतिबिंब करता है/कार्रवाई के मॉडल पैरामीटर को हाइड्रेट करता है और यह बाधा हो सकती है।

  4. उपयोग FormCollection और पोस्ट डेटा दिखाया गया है here मैन्युअल कुंजी और प्रदर्शन सत्यापन द्वारा प्रत्येक मान रही के माध्यम से गणना।

आप और क्या सुझाव देते हैं?


अद्यतन 1

मैं विकल्प 3 के साथ चला गया और एक कस्टम मॉडल बाइंडर कार्यान्वित: AnswerModelBinder : IModelBinder और कहा कि विशिष्ट कार्रवाई विधि में इसका इस्तेमाल किया:

public async Task<ActionResult> ListSaveAsync(
      [ModelBinder(typeof(AnswerModelBinder))]List<AnswerViewModel> questions) 

अब क्या 10 seconds ले लिया पूरा करने के लिए केवल 2 seconds लेता है।

  • ऐसा लगता है कि डिफ़ॉल्ट मॉडल बाइंडर सत्यापन जांच [ModelState] प्रदर्शन पर एक बड़ा प्रभाव डालती है।

अद्यतन 2

मैं सिर्फ यह एक बार फिर अनुभव: एक List<Guid> एक कार्रवाई पैरामीटर के रूप में होने और एक $.getJson कॉल के माध्यम से ही 59 strings गुजर ~ 3 सेकंड ले रहा था के 1 पंक्ति में एक ब्रेकपाइंट हिट करने के लिए कार्रवाई विधि। पैरामीटर प्रकार को List<string> में बदलना पूरी चीज को आंखों के झपकी में बना देता है।

List<Guid> userIds = resources.Select(Guid.Parse).ToList(); 

और यह संसाधनों एक List<Guid> तत्क्षण को List<string> बदल देती है:

एक दिलचस्प तथ्य यह है कि कार्रवाई विधि के अंदर मैं ऐसा किया है।

यकीन के लिए ASP.NET मॉडल बांधने की मशीन के साथ कुछ गाड़ी नहीं है। मैं सिर्फ इतना पता कि यह क्या है चाहते हैं ... :)

+1

धीमी जबाब, Leniel लिए खेद है। आप सर्वर पर कितने सवाल भेज रहे हैं? मॉडल बाइंडर अनुरोध से इनपुट पार्सिंग के बारे में बहुत सामान्य होने के लिए बहुत सारे कोड का उपयोग करता है।मुझे लगता है कि आपके मामले में हल करने का सबसे अच्छा तरीका वह मार्ग था जिसे आपने लिया था। – OdeToCode

+0

@OdeToCode धन्यवाद स्कॉट देखने के लिए स्कॉट ... अच्छा आप कस्टम मॉडल बाइंडर दृष्टिकोण से सहमत हैं। इस विशिष्ट मामले में मैं सर्वर पर 230 प्रश्न भेज रहा हूं। अगर मैं विकल्प # 1 भी करता हूं, तो मुझे लगता है कि यह भी तेज़ होगा ...;) जावास्क्रिप्ट बहुत तेज होने के बाद शायद 2s की बजाय 1s है। इसका परीक्षण करना है। –

+0

@OdeToCode बस कोड को पूरक और कार्यान्वित वर्कअराउंड # 1 मैंने उपरोक्त उल्लेख किया => प्रश्नों को लोड करते समय मैंने प्रत्येक इनपुट/डेटा-एट्रिब्यूट में वर्तमान मान का चयन किया और जब मैं डेटा में उस पिछले मान के साथ मौजूदा मान की तुलना करता हूं विशेषता। मैं इसके साथ मदद करने के लिए jQuery के फ़िल्टर फ़ंक्शन का उपयोग करता हूं। अब बचत तत्काल है। :-) jQuery कोड प्रभावशाली तेज़ है! –

उत्तर

1

इस उत्तर आप देख रहे हैं नहीं हो सकता है, लेकिन यह मदद मिल सकती है। फॉर्मकॉलेक्शन का उपयोग करने के बजाय, नियंत्रक विधि को हस्ताक्षर में एक मॉडल स्वीकार करने का प्रयास करें और Ajax.BeginForm() का उपयोग करें। यह क्रमिकरण की आवश्यकता को हटा देगा, और एमवीसी को इसके काम करने की अनुमति देगा। साथ ही, प्रकार की सूची के साथ एक मॉडल रखने के लायक हो सकता है। यह दृष्टिकोण पद पर मूल्यों के माध्यम से पुन: प्रयास करने की आवश्यकता को भी हटा देगा क्योंकि वे पहले ही मॉडल में होंगे।

+0

इनपुट एंथनी के लिए धन्यवाद। मैं वास्तव में इसकी प्रशंसा करता हूँ। मुझे यह कोशिश करनी होगी ... –

0

मैं इस प्रयास नहीं किया है लेकिन जब मैं पूर्णांक सूचकांक का उपयोग बांधने की मशीन IEnumerable के लिए बाध्य करने में कोई समस्या नहीं थी। चूंकि आप वास्तव में इन गिड्स का उपयोग नहीं कर रहे हैं, इसलिए मैं उन्हें पूर्णांक के साथ बदल दूंगा। (0,1,2 ...)

मुझे लगता है कि आप पृष्ठ कि फार्म या जे एस का उपयोग कर renders पर आसानी से कर सकता है।