दिलचस्प पोस्ट
क्या .NET में यह पता करने का एक तरीका है कि सूची में लिस्ट बी में सभी आइटम शामिल हैं? ASP.NET MVC में बटन क्लिक करने पर आंशिक दृश्य प्रस्तुत करना किसी एकल तालिका में एकाधिक तालिका में INSERT पंक्तियाँ, एक शामिल तालिका से चयन करना किसी भीड़-भाड़ वाले सॉर्ट के साथ लाखों चित्र कैसे रैंक करें 2038 के लिए तैयार करने के लिए हमें क्या करना चाहिए? कक्षा और मॉड्यूल के बीच अंतर मैं XML को सी # ऑब्जेक्ट में कैसे मैप करता हूं क्यों जावा अग्रज तत्व मूल्य नहीं बदलता है? एक साथ बाधाओं को संतुष्ट करने में असमर्थ, बाधा को तोड़ने से पुनर्प्राप्त करने का प्रयास करेंगे द्विअन्तरकारी डबल ड्रॉवर (वाम और दायां दराज एक साथ) प्रारंभिक टेक्स्ट "एक चुनें" के साथ एंड्रॉइड स्पिनर कैसे बनाएं मैं विधि वापसी प्रकार सामान्य कैसे कर सकता हूँ? PHP का उपयोग करते हुए कॉलम में सभी मान कैसे प्राप्त होते हैं? JasperReports में टेक्स्ट फ़ील्ड को स्टाइल करें Enum वर्ग क्यों सादे enum से अधिक पसंद है?

कैसे एमवीसी को IValidatableObject मान्य करने के लिए मजबूर किया जाए

ऐसा लगता है कि जब एमवीसी एक मॉडल को मान्य करता है, जो यह डेटाएनेटेशन एट्रिब्यूट्स (जैसे कि आवश्यक, या श्रेणी) के माध्यम से चलाता है, पहले चला जाता है, और यदि इनमें से कोई भी विफल हो जाता है तो यह मेरे IValidatableObject मॉडल पर मान्य विधि चलाने से चूक जाता है।

क्या कोई तरीका है कि MVC आगे चलकर उस विधि को चलाए, भले ही अन्य सत्यापन विफल हो?

वेब के समाधान से एकत्रित समाधान "कैसे एमवीसी को IValidatableObject मान्य करने के लिए मजबूर किया जाए"

आप वैल्यूएशन कॉन्टैक्स के एक नए इंस्टॉलेशन में पास करके मान्य () को मैन्युअल रूप से कॉल कर सकते हैं, इस प्रकार से:

[HttpPost] public ActionResult Create(Model model) { if (!ModelState.IsValid) { var errors = model.Validate(new ValidationContext(model, null, null)); foreach (var error in errors) foreach (var memberName in error.MemberNames) ModelState.AddModelError(memberName, error.ErrorMessage); return View(post); } } 

इस दृष्टिकोण का एक चेतावनी यह है कि ऐसे मामलों में जहां कोई संपत्ति-स्तर (डेटाअनोटेशन) त्रुटियां नहीं हैं, तो सत्यापन दो बार चलाया जाएगा। इससे बचने के लिए, आप अपने मॉडल में एक संपत्ति जोड़ सकते हैं, एक बूलियन मान्य करें, जिसे आप अपने वैध () विधि में सही पर सेट करते हैं और एक बार चलाते समय मैन्युअल रूप से अपने नियंत्रक में विधि को कॉल करने से पहले जांचें।

तो अपने नियंत्रक में:

 if (!ModelState.IsValid) { if (!model.Validated) { var validationResults = model.Validate(new ValidationContext(model, null, null)); foreach (var error in validationResults) foreach (var memberName in error.MemberNames) ModelState.AddModelError(memberName, error.ErrorMessage); } return View(post); } 

और अपने मॉडल में:

 public bool Validated { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // perform validation Validated = true; } 

प्रत्येक नियंत्रक कार्रवाई के शीर्ष पर बॉयलरप्लेट कोड की आवश्यकता के बिना ऐसा करने का एक तरीका है

आपको अपनी किसी एक के साथ डिफ़ॉल्ट मॉडल बाइंडर को बदलना होगा:

 protected void Application_Start() { // ... ModelBinderProviders.BinderProviders.Clear(); ModelBinderProviders.BinderProviders.Add(new CustomModelBinderProvider()); // ... } 

आपका मॉडल बांधने वाली प्रदाता इस तरह दिखता है:

 public class CustomModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(Type modelType) { return new CustomModelBinder(); } } 

अब एक कस्टम मॉडल बाइंडर बनाओ जो वास्तव में सत्यापन को मजबूर करता है। यह वह जगह है जहां भारी भारोत्तोलन किया गया है:

 public class CustomModelBinder : DefaultModelBinder { protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) { base.OnModelUpdated(controllerContext, bindingContext); ForceModelValidation(bindingContext); } private static void ForceModelValidation(ModelBindingContext bindingContext) { var model = bindingContext.Model as IValidatableObject; if (model == null) return; var modelState = bindingContext.ModelState; var errors = model.Validate(new ValidationContext(model, null, null)); foreach (var error in errors) { foreach (var memberName in error.MemberNames) { // Only add errors that haven't already been added. // (This can happen if the model's Validate(...) method is called more than once, which will happen when // there are no property-level validation failures.) var memberNameClone = memberName; var idx = modelState.Keys.IndexOf(k => k == memberNameClone); if (idx < 0) continue; if (modelState.Values.ToArray()[idx].Errors.Any()) continue; modelState.AddModelError(memberName, error.ErrorMessage); } } } } 

आपको एक अनुक्रमणिकाऑफ़ एक्सटेंशन विधि की भी ज़रूरत होगी। यह एक सस्ती कार्यान्वयन है लेकिन यह काम करेगा:

 public static int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> predicate) { if (source == null) throw new ArgumentNullException("source"); if (predicate == null) throw new ArgumentNullException("predicate"); var i = 0; foreach (var item in source) { if (predicate(item)) return i; i++; } return -1; }