2010-08-31 13 views
29

स्पष्ट रूप से रनटाइम पर गुणों को ऑब्जेक्ट करने के लिए गतिशील रूप से डेटा एन्नोटेशन विशेषताओं को जोड़ना संभव है और इस तरह गतिशील सत्यापन प्राप्त करना संभव है।डेटा एनाटोटेशन गतिशील रूप से गुणों को जोड़ना

क्या कोई इस पर कोड नमूना प्रदान कर सकता है?

उत्तर

39

एमवीसी के पास अपना खुद का मॉडल वैलिडेटेटर प्रदाता प्रदान करने के लिए एक हुक है। डिफ़ॉल्ट रूप से एमवीसी 2 ModelValidatorProvider के उप-वर्ग का उपयोग करता है जिसे DataAnnotationsModelValidatorProvider कहा जाता है जो System.DataAnnotations.ComponentModel.ValidationAttribute मान्यताओं के लिए विशेषता का उपयोग करने में सक्षम है।

डेटाअनोटेशन मॉडल validatorProvider सभी मान्यताओं को खोजने के लिए प्रतिबिंब का उपयोग करता है और केवल आपके मॉडल को सत्यापित करने के लिए संग्रह के माध्यम से लूप करता है। आपको बस इतना करना है कि GetValidators नामक एक विधि को ओवरराइड करें और जो भी स्रोत आप चुनते हैं उससे अपने गुणों को इंजेक्ट करें। मैं इस तकनीक का उपयोग सम्मेलन सत्यापन करने के लिए करता हूं, DataType.Email विशेषता वाले गुण हमेशा एक रेगेक्स के माध्यम से पारित हो जाते हैं, और "गैर-शक्ति" उपयोगकर्ताओं के लिए अधिक प्रतिबंधक सत्यापन लागू करने के लिए डेटाबेस से जानकारी खींचने के लिए इस तकनीक का उपयोग करते हैं।

निम्न उदाहरण बस कहते हैं, "हमेशा आवश्यक किसी भी प्रथम गुण बनाना":

public class CustomMetadataValidationProvider : DataAnnotationsModelValidatorProvider 
{ 
    protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes) 
    { 
     //go to db if you want 
     //var repository = ((MyBaseController) context.Controller).RepositorySomething; 

     //find user if you need it 
     var user = context.HttpContext.User; 

     if (!string.IsNullOrWhiteSpace(metadata.PropertyName) && metadata.PropertyName == "FirstName") 
      attributes = new List<Attribute>() {new RequiredAttribute()}; 

     return base.GetValidators(metadata, context, attributes); 
    } 
} 

आपको बस इतना करना है अपने Global.asax.cs फ़ाइल में प्रदाता रजिस्टर है:

protected void Application_Start() 
    { 
     ModelValidatorProviders.Providers.Add(new CustomMetadataValidationProvider()); 

     AreaRegistration.RegisterAllAreas(); 

     RegisterRoutes(RouteTable.Routes); 
    } 

अंतिम परिणाम:

end result

w इस मॉडल के ith:

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public DateTime Birthday { get; set; } 
} 
+1

इस महान सामान jfar! ;) मुझे लगता है कि आपने मुझे वीएबी में गहरा गोता बचाया है .. – mare

+0

इस उत्तर में उदाहरण कोड के साथ एक समस्या है गुणों को दो बार संसाधित किया जा सकता है: एक बार 'डेटा एन्नोटेशन मॉडेल वैलिडेटेटरप्रोवाइडर' के आपके उप-वर्ग द्वारा और एक बार पूर्व-मौजूदा एक द्वारा। इससे त्रुटियां हो सकती हैं। मुझे लगता है कि यह केवल उन गुणों को पास करना बेहतर है जिन्हें आप कॉल से जोड़ रहे हैं, इससे बचने के लिए 'बेस.गेटालिडेटर्स' पर कॉल करें। – Sam

+1

इसके अलावा, एएसपी.नेट एमवीसी 4 (और संभवतः अन्य) में, 'आधार। गेटवालिडेटर्स' स्वचालित रूप से 'आवश्यक एट्रिब्यूट' जोड़ता है जब 'मेटाडेटा। Isequequired'' सत्य' है। इसे रोकने के लिए एक तरीका 'आधार। गेटवालिडेटर्स' को कॉल करने से पहले 'मेटाडाटा।' अपेक्षित 'को' झूठी 'पर सेट करना है। आप इसे कॉल के बाद मूल मूल्य पर वापस सेट कर सकते हैं। – Sam

1

मुझे नहीं लगता कि आप रनटाइम पर सदस्यों को विशेषताओं को जोड़ सकते हैं, लेकिन आप शायद इसे आपके लिए संभालने के लिए कस्टम मेटाडेटा प्रदाता का उपयोग कर सकते हैं।

आपको this blog post देखें।

+4

क्या देता है? नकारात्मक वोट और कोई टिप्पणी नहीं? –

+1

मैं नहीं था जो डाउनवॉटेड था, लेकिन मैं कहूंगा कि यह लिंक-केवल उत्तर स्कीफ टेस्ट पास नहीं करता है मरने का लिंक था (जैसा वर्तमान में बीटीडब्ल्यू है)। यह एक साइनपॉस्ट है, शायद एक अच्छा है, लेकिन उपयोगकर्ताओं को अभी भी लागू करने के लिए साइट से बाहर जाने की आवश्यकता होगी। अधिक इनलाइन विवरण प्रदान करने या किसी टिप्पणी में कनवर्ट करने पर विचार करें, या यहाँ और वहां ग़लत वोट स्वीकार करें। – KyleMit

+2

निश्चित रूप से क्या हुआ है, क्योंकि यह लिंक अब मर चुका है। – StevoInco

8

अपने Global.asax में आप नया जोड़ने से पहले ModelValidatorProviders स्पष्ट करने के लिए है। अन्यथा यह प्रत्येक एनोटेशन को दो बार जोड़ देगा जो आपको "अविभाज्य क्लाइंट सत्यापन नियमों में सत्यापन प्रकार नाम अद्वितीय होना चाहिए।" - त्रुटि।

protected void Application_Start() 
{ 
    ModelValidatorProviders.Providers.Clear(); 
    ModelValidatorProviders.Providers.Add(new CustomMetadataValidationProvider()); 

    AreaRegistration.RegisterAllAreas(); 

    RegisterRoutes(RouteTable.Routes); 
} 
0

एक ओवरराइड GetValidators के साथ एक कस्टम MetadataValidationProvider का उपयोग कर के दृष्टिकोण में कुछ कमजोरियों है:

  • ऐसे DisplayAttribute के रूप में कुछ गुण सत्यापन से संबंधित नहीं हैं, इसलिए उन्हें सत्यापन के स्तर पर जोड़ने doesn ' टी काम नहीं
  • यह भविष्य के सबूत नहीं हो सकता है; एक ढांचा अद्यतन यह काम करना बंद कर सकता है।

आप अपने डायनामिक रूप से लागू किया डेटा एनोटेशन लगातार काम करना चाहते हैं, तो आप DataAnnotationsModelMetadataProvider और DataAnnotationsModelValidatorProvider उपवर्ग कर सकते हैं। ऐसा करने के बाद, को फ्रेमवर्क के ModelMetadataProviders.Current और ModelValidatorProviders.Providers के माध्यम से एप्लिकेशन स्टार्ट-अप पर प्रतिस्थापित करें। (आप इसे Application_Start में कर सकते हैं।)

जब आप अंतर्निर्मित प्रदाताओं को उप-वर्गीकृत करते हैं, तो अपने स्वयं के गुणों को लागू करने के लिए एक व्यवस्थित और उम्मीदवार भविष्य के सबूत तरीके GetTypeDescriptor को ओवरराइड करना है। मैंने इसे सफलतापूर्वक किया है, लेकिन इसमें ICustomTypeDescriptor और PropertyDescriptor का कार्यान्वयन शामिल है, जिसमें बहुत सारे कोड और समय की आवश्यकता होती है।

संबंधित मुद्दे