2011-07-01 10 views
5

एएसपीनेट एमवीसी में एक आम अनुशंसित अभ्यास है कि you should not send your business models to your views .. इसके बजाय आपको प्रत्येक दृश्य के लिए विशिष्ट व्यूमोडेल बनाना चाहिए।आप अपना सत्यापन asp.net mvc 3 में कहां रखते हैं?

जब यह किया जाता है और आप अपने नियंत्रक में ModelState.IsValid विधि को कॉल करते हैं तो आप प्रभावी रूप से व्यूमोडेल की वैधता की जांच कर रहे हैं लेकिन व्यवसाय ऑब्जेक्ट नहीं।

इससे निपटने के लिए पारंपरिक दृष्टिकोण क्या है?

public class Person 
{ 
public int ID {get; set;}; 

[Required] 
public string Name {get; set;} 

[Required] 
public string LastName {get; set;} 

public virtual ICollection<Exam> Exams {get; set;} 

} 

public class PersonFormViewModel 
{ 

public int ID {get; set;};  


[Required] 
public string Name {get; set;} 

[Required] 
public string LastName {get; set;} 

} 

यह वही है मैं अभी है, लेकिन मैं निश्चित नहीं करता है, तो [आवश्यक] विशेषता दोनों मॉडल या सिर्फ ViewModel या सिर्फ बिजनेस मॉडल पर प्रकट होने चाहिए वास्तव में है।

इस मुद्दे पर किसी भी सुझाव की सराहना की जाती है।

मेरे दावे का समर्थन करने के लिए और अधिक लिंक यह है कि हमेशा दृश्य मॉडल का उपयोग करना एक आम अच्छा अभ्यास है।

How to add validation to my POCO(template) classes

http://blogs.msdn.com/b/simonince/archive/2010/01/26/view-models-in-asp-net-mvc.aspx

+0

आपका "व्यावसायिक मॉडल" वास्तव में क्या है? –

+0

व्यक्ति एक वर्ग है जिसे एंटीटीफ्रेमवर्क द्वारा ट्रैक किया जाता है। PersonViewModel स्पष्ट रूप से नहीं है .. मैंने जिस ब्लॉग पोस्ट से लिंक किया है उसे पढ़ें और आप उन अभ्यासों को समझेंगे जिन्हें मैं अनुवर्ती करने का प्रयास कर रहा हूं .. इसलिए सवाल यह है कि सत्यापन तर्क कहां जाना चाहिए। – ignaciofuentes

+0

धन्यवाद - क्षमा करें, मैंने लेख स्कैन किया और इसके भीतर "व्यापार मॉडल" की खोज की लेकिन कोई हिट नहीं। –

उत्तर

7

मेरी प्राथमिकता दृश्य मॉडल पर इनपुट सत्यापन और डोमेन मॉडल पर व्यापार सत्यापन करना है।

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

और आपके पास शायद व्यवसाय/डोमेन नियम होंगे जो कि केवल "फ़ॉर्म" से अधिक पर भरोसा करते हैं, इसलिए आपको डोमेन मॉडल में ऐसा करना चाहिए (सत्यापन के बाद सत्यापन को निष्पादित करें), या एक के साथ सेवा परत

हमारे सभी मॉडल में "मान्य" नामक एक विधि है, जिसे हम जारी रखने से पहले सेवाओं में कॉल करते हैं। वे कस्टम अपवाद फेंक देते हैं यदि वे व्यावसायिक सत्यापन विफल करते हैं, जो नियंत्रक द्वारा पकड़ा जाता है और मॉडल स्थिति में भी जोड़ा जाता है।

हर किसी के कप चाय नहीं हो सकता है, लेकिन यह लगातार है।व्यवसाय सत्यापन के

उदाहरण के लिए, के रूप में अनुरोध:

public abstract class Post 
{ 
    // .. fields, properties, domain logic, etc 

    public void Validate() 
    { 
     if (!this.GeospatialIdentity.IsValidForThisTypeOfPost()) 
     throw new DomainException(this, BusinessException.PostNotValidForThisSpatial.); 
    } 
} 
:

यहाँ (आदि सवाल, फोटो, वीडियो,) एक डोमेन मॉडल हमारे पास है, जो एक सामान्य "पोस्ट" का प्रतिनिधित्व करता है, इसका एक उदाहरण

आप वहां देखते हैं, मैं व्यवसाय नियमों के खिलाफ जांच कर रहा हूं, और कस्टम अपवाद फेंक रहा हूं। DomainException हमारा आधार है, और हमारे पास कई व्युत्पन्न कार्यान्वयन हैं। हमारे पास BusinessException नामक एक enum है, जिसमें हमारे सभी अपवादों के लिए मूल्य शामिल हैं। हम संसाधन-आधारित त्रुटि संदेश प्रदान करने के लिए enum पर एक्सटेंशन विधियों का उपयोग करते हैं।

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

अब, नियंत्रक:

[HttpPost] 
public ActionResult Create(QuestionViewModel viewModel) 
{ 
    if (!ModelState.IsValid) 
    return View(viewModel); 

    try 
    { 
     // Map to ViewModel 
     var model = Mapper.Map<QuestionViewModel,Question>(viewModel); 

     // Save. 
     postService.Save(model); // generic Save method, constraint: "where TPost: Post, new()". 

     // Commit. 
     unitOfWork.Commit(); 

     // P-R-G 
     return RedirectToAction("Index", new { id = model.PostId }); 
    } 
    catch (Exception exc) 
    { 
     var typedExc = exc as DomainException; 

     if (typedExc != null) 
     { 
     // Internationalised, user-friendly domain exception, so we can show 
     ModelState.AddModelError("Error", typedExc.BusinessError.ToDescription()); 
     } 
     else 
     { 
     // Could be anything, e.g database exception - so show generic msg. 
     ModelState.AddModelError("Error", "Sorry, an error occured saving the Post. Support has been notified. Please try again later."); 
     } 
    } 

    return View(viewModel); 
} 

तो, जब भी हम सेवा पर "सहेजें" विधि करने के लिए मिल द्वारा, मॉडल बीत चुका है इनपुट सत्यापन। फिर सहेजें विधि post.Validate() पर कॉल करती है, व्यवसाय नियमों का आह्वान करती है।

यदि कोई अपवाद उठाया जाता है, तो नियंत्रक इसे पकड़ता है और संदेश प्रदर्शित करता है। यदि यह सेव विधि पास हो जाता है और दूसरी त्रुटि होती है (उदाहरण के लिए 90%, यह इकाई फ्रेमवर्क है), हम एक सामान्य त्रुटि संदेश दिखाते हैं।

जैसा कि मैंने कहा, सभी के लिए नहीं, लेकिन यह हमारी टीम के लिए अच्छा काम करता है। सफलता के बाद रीडायरेक्ट में हमारे पास प्रस्तुति और डोमेन सत्यापन का स्पष्ट पृथक्करण है, और कच्चे HTTP पोस्ट से नियंत्रण का लगातार प्रवाह होता है।

HTH

+0

क्या आप इस का एक छोटा सा उदाहरण पोस्ट करना चाहते हैं? विशेष रूप से नियंत्रक विधि। – ignaciofuentes

+2

@NachoF - जैसा कि आप चाहते हैं, उदाहरण जोड़ा गया। – RPM1984

0

आमतौर पर अपने ViewModel अपने मॉडल के लिए एक संदर्भ में शामिल होंगे - एक ViewModel, अगर आप अपने दृश्य में अतिरिक्त जानकारी है कि अपने मॉडल में उपलब्ध नहीं है प्रदर्शित करने के लिए की जरूरत है केवल आवश्यक है वहाँ पहले से मौजूद डेटा को दोहराने की जरूरत नहीं है।

+0

तो आप जो कह रहे हैं वह यह है कि आप अपने व्यावसायिक मॉडल ऑब्जेक्ट को उस दृश्य में पास करते हैं जब आपको अतिरिक्त जानकारी की आवश्यकता नहीं होती है जो व्यवसाय ऑब्जेक्ट में स्वयं नहीं है? – ignaciofuentes

+0

सही, उदाहरण के लिए यहां http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx स्कॉट गुथरी अपने व्यक्ति प्रकार को पास करता है जिसमें डेटा एनोटेशन होते हैं नियंत्रक में उसका विचार। – devdigital

+0

मैंने अभी लिखा है कि लेख लिखा है, और कहीं भी नहीं देख सकता है जहां जिमी कहता है 'आपको अपने विचारों को अपने व्यापार मॉडल नहीं भेजना चाहिए'। वास्तव में लेख 'नहीं' लेख में कहीं भी नहीं दिखाई देता है और जिमी राज्यों 'निश्चित रूप से, इनमें से कई राय केवल हमारी परियोजना की बाधाओं में वास्तव में मान्य हैं' और 'ये राय परियोजना पर लागू हो सकती हैं या नहीं भी हो सकती हैं पर काम। दोबारा, पैटर्न ट्रेडऑफ, लाभ और देनदारियों के बारे में हैं ' – devdigital

4

मेटाडेटा "दोस्त" वर्ग बिल्कुल यही है। सत्यापन एक बार बनाई गई है, लेकिन दोनों मॉडल और viewmodel कक्षाएं पर इस्तेमाल किया जा सकता:

public class PersonMetaData 
{ 
    [Required] 
    public string Name {get; set;} 

    [Required] 
    public string LastName {get; set;} 
} 

[MetadataType(typeof(PersonMetaData))] 
public class Person 
{ 
    public string Name {get; set;} 
    public string LastName {get; set;} 
} 

[MetadataType(typeof(PersonMetaData))] 
public class PersonFormViewModel 
{ 
    public string Name {get; set;} 
    public string LastName {get; set;} 
} 
+0

बीयूटी एक संपूर्ण बिजनेस क्लास को एक व्यू में पास करने और संपादन मोड के रूप में उपयोग करने के लिए व्यूमोडेल के रूप में उपयोग करने और इसे नियंत्रक को वापस सबमिट करने और इसे ओएमएम एक्स 1000 विचारों में एक मिनट वीएस में पास करने के लिए एक व्यूमोडेल विशिष्ट का उपयोग करके एक बार वीएस में पास करने के लिए छिद्रण प्रभाव क्या हैं सही डेटा में परिवर्तित होने के लिए उस मॉडल को व्यापार में देखें और पास करें। डेटा हमेशा व्यस्त रहेगा लेकिन व्यूइंजिन में व्यस्त सर्वरों के लिए दोस्त वर्ग ओवरहेड को कैसे प्रभावित करते हैं? निश्चित रूप से यह फ्लिपिन आसान है लेकिन सर्वर को थ्रैश करना भी आसान है क्योंकि हमें इन कार्यों के प्रभावों का एहसास नहीं है। – ppumkin

1

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

2

RPM1984 द्वारा महान जवाब है, और अच्छा कोड नमूना।

मेरा विचार अभी भी है कि शुरुआत से संस्करण 2 का उपयोग करना उत्पादकता और संरचना के बीच एक व्यावहारिक संतुलन है, लेकिन आपको हमेशा कुछ मामलों में संस्करण 3 में जाने के लिए तैयार रहना होगा, इसलिए मैं दो दृष्टिकोणों का मिश्रण करने का समर्थन करता हूं तार्किक। पैटर्न & प्रैक्टिस हालांकि हमेशा वेरिएंट 3 करने की सलाह देते हैं क्योंकि यह चिंताओं का आदर्श पृथक्करण है, और यह आपको उसी समाधान में दो दृष्टिकोणों का उपयोग करने से बचाता है, जो कुछ लोग पसंद नहीं करते हैं और कई ग्राहक मैं वेरिएंट 3 चुनने के साथ काम करता हूं और उसके साथ चलता हूं सभी मॉडलों के लिए।

मुझे लगता है कि कुंजी क्या है आरपीएम 1 9 84 ने कहा - आपके व्यू मॉडल के अंदर अपनी व्यावसायिक संस्थाओं का पुन: उपयोग करना सत्यापन का पुन: उपयोग करने के लिए उपयोगी है, लेकिन ध्यान रखें कि अक्सर आपके व्यवसाय तर्क को अलग-अलग सत्यापन करने की आवश्यकता होती है (उदाहरण के लिए जांच रिकॉर्ड पहले से मौजूद नहीं है)। यदि आप वेरिएंट 3 का उपयोग करते हैं तो यह आपको अपने विचारों की आवश्यकताओं पर पूरी तरह से अपने दृश्य मॉडल सत्यापन पर ध्यान केंद्रित करने की शक्ति देता है (थोड़ा अतिरिक्त प्रयास के खर्च पर) लेकिन आपको हमेशा किसी प्रकार की व्यावसायिक तर्क सत्यापन की आवश्यकता होगी।

+0

यदि आपके पास कहने के लिए कुछ भी नया नहीं है, तो आपको उत्तर, या अपवोट के बजाय टिप्पणी का उपयोग करना चाहिए। –