2010-08-25 13 views
6

मेरी ASP.NET MVC ऐप्लिकेशन में के लिए एक इंटरफेस पासिंग, मैं एक अंतरफलक है जो कई अलग दृष्टिकोण मॉडल के लिए टेम्पलेट के रूप में कार्य करता है है:एक ASP.NET MVC नियंत्रक लड़ाई विधि

public interface IMyViewModel 
{ 
    Client Client1 { get; set; } 
    Client Client2 { get; set; } 

    Validator Validate(); 
} 

तो, मेरे विचार मॉडल इस तरह परिभाषित कर रहे हैं:

public interface MyViewModel1 : IMyViewModel 
{ 
    Client Client1 { get; set; } 
    Client Client2 { get; set; } 

    // Properties specific to MyViewModel1 here 

    public Validator Validate() 
    { 
     // Do ViewModel-specific validation here 
    } 
} 

public interface MyViewModel2 : IMyViewModel 
{ 
    Client Client1 { get; set; } 
    Client Client2 { get; set; } 

    // Properties specific to MyViewModel2 here 

    public Validator Validate() 
    { 
     // Do ViewModel-specific validation here 
    } 
} 

तब मैं वर्तमान में एक अलग नियंत्रक कार्रवाई प्रत्येक अलग प्रकार के लिए सत्यापन करना है मॉडल बंधन का उपयोग कर:

[HttpPost] 
public ActionResult MyViewModel1Validator(MyViewModel1 model) 
{ 
    var validator = model.Validate(); 

    var output = from Error e in validator.Errors 
       select new { Field = e.FieldName, Message = e.Message }; 

    return Json(output); 
} 

[HttpPost] 
public ActionResult MyViewModel2Validator(MyViewModel2 model) 
{ 
    var validator = model.Validate(); 

    var output = from Error e in validator.Errors 
       select new { Field = e.FieldName, Message = e.Message }; 

    return Json(output); 
} 

यह ठीक काम करता है- लेकिन अगर मेरे पास 30 अलग-अलग दृश्य मॉडल प्रकार होते हैं तो 30 अलग नियंत्रक क्रियाएं होंगी, सभी समान कोड विधि हस्ताक्षर से अलग कोड, जो खराब अभ्यास की तरह लगता है।

मेरा सवाल यह है कि, मैं इन सत्यापन कार्यों को कैसे समेकित कर सकता हूं ताकि मैं किसी भी प्रकार का व्यू मॉडल पास कर सकूं और इसकी वैधता() विधि को कॉल कर सकूं, बिना किसी प्रकार के देखभाल के?

पहले तो मुझे कार्रवाई पैरामीटर के रूप इंटरफेस ही उपयोग करने की कोशिश:

public ActionResult MyViewModelValidator(IMyViewModel model)... 

लेकिन यह काम नहीं किया: मैं एक Cannot create an instance of an interface अपवाद मिलता है। मैंने सोचा कि मॉडल का एक उदाहरण नियंत्रक कार्रवाई में पारित किया जाएगा, लेकिन स्पष्ट रूप से यह मामला नहीं है।

मुझे यकीन है कि मुझे कुछ आसान याद आ रहा है। या शायद मैंने अभी यह सब गलत किया है। क्या कोई मेरी मदद कर सकता है?

उत्तर

10

कारण आप इंटरफ़ेस का उपयोग नहीं कर सकते कारण serialization की वजह से है। एक अनुरोध की बात आती है में यह केवल स्ट्रिंग कुंजी/मान जोड़े उस वस्तु का प्रतिनिधित्व शामिल हैं:

"Client1.Name" = "John" 
"Client2.Name" = "Susan" 

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

क्या आप एक सहायक लिख सकता है दोहराया कोड निकालना चाहते हैं:

[HttpPost]   
public ActionResult MyViewModel1Validator(MyViewModel1 model)   
{   
    return ValidateHelper(model);   
}   

[HttpPost]   
public ActionResult MyViewModel2Validator(MyViewModel2 model)   
{   
    return ValidateHelper(model);   
} 

private ActionResult ValidateHelper(IMyViewModel model) { 
    var validator = model.Validate();   

    var output = from Error e in validator.Errors   
       select new { Field = e.FieldName, Message = e.Message };   

    return Json(output); 
} 

हालांकि, अगर आप अभी भी एक मॉडल के प्रकार के लिए एक अलग कार्रवाई विधि की आवश्यकता होगी। शायद आपके अन्य तरीकों से आप अपने कोड को दोबारा कर सकते हैं। ऐसा लगता है कि आपके मॉडल वर्गों में एकमात्र अंतर वैधता व्यवहार है। आप अपने मॉडल वर्ग में सत्यापन प्रकार को एन्कोड करने का एक अलग तरीका ढूंढ सकते हैं।

+0

मैं पूरी तरह से समय की बाधाओं के कारण इस दृष्टिकोण के लिए गया था, लेकिन आपने यह भी समझाया कि ऑब्जेक्ट पहले से ही एक उदाहरण क्यों नहीं है जब यह नियंत्रक में पास हो जाता है, जो जानना उपयोगी होता है। –

1

आप इंटरफ़ेस की बजाय बेस क्लास का उपयोग करने पर विचार कर सकते हैं।

+0

परिणामस्वरूप यह एक ही त्रुटि संदेश में होता है। यह या तो एक अमूर्त प्रकार का उदाहरण नहीं बना सकता है। –

+1

आप गैर-सार आधार वर्ग का उपयोग कर सकते हैं। –

1

मुझे लगता है कि मैं एक अमूर्त बेस क्लास तैयार करूंगा जो IMyViewModel को कार्यान्वित करे। मैं एक अमूर्त विधि को मान्य कर दूंगा और मेरे कंक्रीट व्यू मॉडल में ओवरराइडिंग की आवश्यकता होगी जो MyAbstractViewModel से विरासत में मिला है। अपने नियंत्रक के अंदर, यदि आप चाहते हैं तो आप IMyViewModel इंटरफ़ेस के साथ काम कर सकते हैं, लेकिन बाध्यकारी और क्रमबद्धता को वास्तव में बांधने के लिए एक ठोस वर्ग की आवश्यकता होती है। मेरा $ .02।

+1

मुझे एक अतिरिक्त टिप्पणी जोड़नी चाहिए - मैं वास्तव में अमूर्त वर्ग को नियंत्रक में नहीं, बल्कि कंक्रीट वर्ग में पास करूंगा। आपके पास एक सत्यापन सेवा या कुछ अन्य विधि हो सकती है जो अमूर्त वर्ग या इंटरफ़ेस को संभाल सकती है लेकिन स्पष्टता के लिए, आपको वास्तव में यह उम्मीद करनी चाहिए कि आप अपने नियंत्रक में क्या प्राप्त कर रहे हैं। – Hal

4

आप इसे देख सकते हैं: http://msdn.microsoft.com/en-us/magazine/hh781022.aspx

ऐसा इसलिए होता है क्योंकि DefaultModelBinder के पास यह जानने का कोई तरीका नहीं है कि किस प्रकार के IMyViewModel को बनाना चाहिए। समाधान के लिए, आप कस्टम मॉडल बाइंडर बनाते हैं और यह इंगित करते हैं कि इंटरफ़ेस का उदाहरण कैसे बनाएं और बाध्य करें।

+0

+1 IMHO यह जाने का तरीका है, अन्य सभी उत्तरों को ट्रम्प करता है (जिनमें से कुछ स्पष्ट रूप से वास्तविक दुनिया में परीक्षण नहीं किए गए हैं)। –

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