2015-01-26 8 views
5

तो मैं अपने Models निर्देशिका में एक इकाई मिल गया है:नियंत्रक के अंदर एक दृश्य मॉडल का उपयोग करते समय मैं इकाई के अंदर सत्यापन नियम कैसे रखूं?

public class Event 
{ 
    public int Id { get; set; } 

    [Required, MaxLength(50), MinLength(3)] 
    public string Name { get; set; } 

    [Required, MaxLength(2000)] 
    public string Description { get; set; } 
} 

और मैं एक ViewModel का उपयोग कर विचारों को इसे उजागर करना चाहते हैं:

public class BaseEventViewModel 
{ 
    public string Name { get; set; } 

    [DataType(DataType.MultilineText)] 
    public string Description { get; set; } 
} 

public class EventCreateViewModel : BaseEventViewModel 
{ 

} 

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

तो मैं नया दृश्य मॉडल का उपयोग करने के लिए अपने नियंत्रक बदल दिया है:

[HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Create(EventCreateViewModel viewModel) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Events.Add(new Event 
      { 
       Name = viewModel.Name, 
       Description = viewModel.Description 
      }); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 

     return View(viewModel); 
    } 

हालांकि इकाई सत्यापन में से कोई भी हो जाता है और मैं एक खाली रूप है जो एक DbEntityValidationException अपवाद को जन्म देती है प्रस्तुत करने में सक्षम हूँ।

संभवतः ऐसा इसलिए है क्योंकि ModelState.IsValid दृश्य मॉडल पर काम कर रहा है, न कि दृश्य मॉडल का प्रतिनिधित्व करने वाली इकाई। मैं इन सत्यापन त्रुटियों को कैसे पकड़ सकता हूं?

उत्तर

0

इस मामले में, आपके सत्यापन नियम दृश्य मॉडल पर होना चाहिए। जो काम आप कर रहे हैं वह सत्यापन उपयोगकर्ता इनपुट है, और यही वह इनपुट है जो आप इनपुट प्राप्त करने के लिए कर रहे हैं।

आपके पास डेटाबेस पर लिखे जाने से पहले इकाई पर एक अलग सत्यापन चरण हो सकता है। उस स्थिति में, आप इकाई पर नियमों को संभालने के लिए एक अलग सत्यापन तंत्र का उपयोग करेंगे।

+0

मैं वहाँ उम्मीद थी एक क्लीनर समाधान होगा उस के लिए, अब के रूप में मैं एक ही डेटा एनोटेशन के लिए कई दृश्य मॉडल के चारों ओर बिखरे हुए हैं। अगर मैं एक बदलता हूं, तो मुझे उन सभी को बदलना याद रखना होगा। :/ –

+0

जरूरी नहीं है। यदि आप ViewModel से प्राप्त डेटा के साथ कुछ भी नहीं कर रहे हैं, तो फिर से सत्यापित करने का कोई कारण नहीं है। आपको केवल यह सत्यापित करने की आवश्यकता है कि आपका प्रोग्राम उपयोगकर्ता इनपुट को बदलने जा रहा है या नहीं। –

+2

@KingIsaac - दृश्य को उपयोगकर्ता पर भरोसा नहीं करना चाहिए, नियंत्रक को विश्वास पर भरोसा नहीं करना चाहिए, डेटाबेस को कॉलर पर भरोसा नहीं करना चाहिए। प्रत्येक चरण (यहां तक ​​कि डीबी) पर प्रमाणीकरण अच्छा विचार है और इसे छोड़ना नहीं चाहिए। – fex

1

मॉडल एक्शन विधि पैरामीटर के माध्यम से पारित किया गया है। क्षमा करें - इसे प्राप्त करने का एकमात्र तरीका डेटा एनोटेशन को ViewModels में भी जोड़ना है।

संपादित करें: यह प्रतिबिंब के साथ क्रम पर संलग्न किया जा सकता है (ताकि Entity सत्यापन में परिवर्तन स्वचालित रूप से हो सकता है ViewModels पर "देखा") - हालांकि कि काम का एक बहुत कुछ है। आपको DataAnnotationsModelValidatorProvider से उत्तराधिकारी होना होगा, एप्राइपिएट Entity क्लास गुणों से सभी विशेषताओं को प्राप्त करें और उन्हें व्यूमोडेल में जोड़ें। मुझे लगता है कि Entity और Viewmodels सत्यापन नियमों के लिए यूनिट परीक्षण लिखना सबसे अच्छा तरीका है (Entity और ViewModel में फ़ील्ड में संलग्न समान गुण हैं) - अलग-अलग वैधकर्ता बग से बचने के लिए।

इस तरह की समस्या को हल करने के लिए दूसरा अच्छा तरीका (और सबसे तेज़ एक) AOP फ्रेमवर्क PostSharp जैसे फ्रेमवर्क का उपयोग करना है। पहलू बनाएं: EntityNameValidatorAspect (उचित गुण मान वाले संपत्ति के लिए डेटा एनोटेशन जोड़ने के लिए)। फिर आप Entity और Viewmodel में नाम संपत्ति से पहले इस पहलू ([EntityNameValidatorAspect]) को जोड़ देंगे। यह विधि के लिए बार-बार कोड को दोबारा करने का एक समानता है - आप केवल कुछ सामान्य विशेषताओं को "रिफैक्टर" करते हैं।

4

मुझे सही दिशा में प्रबल होने के बाद वास्तव में उत्तर मिला। अब जब मैं एक खाली फार्म मैं सामान्य रूप में दिखाया गया हो सत्यापन त्रुटियों प्रस्तुत

[MetadataType(typeof(Event))] 
public class BaseEventViewModel 
{ 
    public int Id { get; set; } 

    public string Name { get; set; } 

    [DataType(DataType.MultilineText)] 
    public string Description { get; set; } 
} 

: मैं मेरे विचार मॉडल को यह टिप्पणी जोड़ने, तो यह मेरी इकाई पर गुण के लिए आवेदन किया एनोटेशन के सभी प्राप्त कर लेगा।

यह मेरे व्यू मॉडल के अंदर फिर से हर संपत्ति को दोबारा परिभाषित करने की चेतावनी के साथ आता है, जो एक दृश्य मॉडल के बिंदु को केवल उस गुण को हरा देता है जो आपको आवश्यक गुणों को पकड़ता है, हालांकि यह मेरे मामले के लिए काम करता है।

+0

'यह मेरे दृश्य मॉडल के अंदर फिर से हर संपत्ति को फिर से परिभाषित करने की चेतावनी के साथ आता है' आप अपने दृश्य मॉडल में 'ईवेंट' ऑब्जेक्ट डाल सकते हैं। इससे आपकी समस्याएं हल हो जाएंगी। – Shoe

+0

@Shoe और यह कुछ भयानक अपवादों को ट्रिगर करेगा उदाहरण के लिए ओआरएम आलसी लोडिंग – fex

+0

@fex निश्चित रूप से, लेकिन आप हमेशा आईडी आईडी के आधार पर एक नई इकाई के लिए एक लुकअप कर सकते हैं। वास्तव में एक गैर मुद्दा। – Shoe

0

मुझे लगता है कि गतिशील एनोटेशन ExpressiveAnnotations AOP समान पैटर्न

का उपयोग कर आप किसी भी तर्क आप का सपना कर सकते हैं मान्य सकता है करता है इस अद्भुत nuget उपयोग कर रहे हैं:

public string Email { get; set; } 
public string Phone { get; set; } 
[RequiredIf("Email != null")] 
[RequiredIf("Phone != null")] 
[AssertThat("AgreeToContact == true")] 
public bool? AgreeToContact { get; set; } 
संबंधित मुद्दे