2010-10-25 11 views
11

तो मैं निम्नलिखित दृढ़ता से टाइप दृश्य है:ASP.NET MVC 2 - सार मॉडल के लिए बाध्य

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<XXX.DomainModel.Core.Locations.Location>" %> 

कहाँ स्थान एक अमूर्त वर्ग है।

और मैं निम्नलिखित नियंत्रक है, जो एक पोस्ट के माध्यम से एक जोरदार टाइप मॉडल स्वीकार करता है:

[HttpPost] 
public ActionResult Index(Location model) 

मैं बताते हुए एक रनटाइम त्रुटि मिलती है "नहीं बना सकते सार कक्षा

कौन सा की पाठ्यक्रम समझ में आता है। हालांकि - मुझे यकीन नहीं है कि सबसे अच्छा समाधान क्या है।

मेरे पास कई ठोस प्रकार हैं (लगभग 8), और यह एक दृश्य है जहां आप सी अमूर्त वर्ग का एकमात्र संपादन गुण।

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

[HttpPost] 
public ActionResult Index(City model) 
{ 
    UpdateLocationModel(model); 
    return View(model); 
} 

[HttpPost] 
public ActionResult Index(State model) 
{ 
    UpdateLocationModel(model); 
    return View(model); 
} 

आदि आदि

और फिर:

[NonAction] 
private void UpdateLocationModel (Location model) 
{ 
    // ..snip - update model 
} 

लेकिन यह या तो, MVC शिकायत कार्रवाई तरीकों अस्पष्ट हैं (यह भी समझ में आता है) काम नहीं करता।

हम क्या करते हैं? क्या हम बस एक अमूर्त मॉडल से बंधे नहीं जा सकते?

+1

अच्छा प्रश्न है। जवाब देखने में रूचि! –

+0

मुझे उत्सुकता है यदि आपको कभी इसे संभालने का बेहतर तरीका मिल गया है? –

+0

@ मिस्टर मैन - नहीं। मुझे इसे फिर से नहीं करना पड़ा। अगर मैंने किया, तो मैं वही करूँगा जो स्वीकार किए गए उत्तर से पता चलता है। – RPM1984

उत्तर

7

इस सार वर्ग के लिए एक कस्टम मॉडल बांधने की मशीन लिखने के बारे में कैसे:

public class CustomBinder : DefaultModelBinder 
{ 
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) 
    { 
     // TODO: based on some request parameter choose the proper child type 
     // to instantiate here 
     return new Child(); 
    } 
} 

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

+0

वैसे यह एक बहुत ही सरल दृश्य है, अमूर्त मॉडल पर गुणों के लिए फ़ील्ड संपादित करें। तो मैं इस एचटीएमएल को कई दृढ़ता से टाइप किए गए विचारों में "डुप्लिकेट" नहीं करना चाहता था। मैं कस्टम मॉडल बाइंडर्स में एक नज़र डालेगा - क्योंकि जब मैं दृश्य प्रस्तुत करता हूं तो मुझे बच्चे के प्रकार पता है। मैं कल कार्यालय को आजमाउंगा - चीयर्स। – RPM1984

+0

ठीक है, मैंने मॉडल बाइंडर्स का एक पठन किया है, और मैं सहमत हूं - यह मेरे परिदृश्य में समझ में नहीं आता है। मैं ठोस दृश्य मॉडल के साथ चिपकने जा रहा हूँ। यह हालांकि काम करेगा, इसलिए मैं आपका जवाब स्वीकार करूंगा। धन्यवाद। – RPM1984

1

बस इसे बाहर फेंकने के लिए - मुझे बहुत अधिक दिलचस्पी है कि दूसरों का क्या जवाब हो सकता है, लेकिन यही वह मामला है जो मैंने इसी तरह की स्थिति में किया था;

असल में, मैं कार्रवाई विधि में पैरामीटर के रूप मॉडल वर्ग का उपयोग नहीं किया, बजाय FormCollection में गुजर और एक जोड़े में जाना जाता discriminators परीक्षण जो प्रकार बनाने के लिए/संपादन, फिर वहाँ से TryUpdateModel इस्तेमाल किया यह पता लगाने की।

ऐसा लगता है कि एक बेहतर तरीका हो सकता है, लेकिन मैं इसके बारे में और सोचने के लिए कभी नहीं मिला।

+0

हाँ, यह मेरा अगला कदम था! :) लेकिन एए, मैं दृढ़ता से टाइप की गई भलाई नहीं करूँगा। :) – RPM1984

+0

यह स्वादिष्ट, और पौष्टिक है; इस पूरे नाश्ते का हिस्सा! –

3

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

Application_Start (में अपने Global.asax.cs फ़ाइल में):

ModelBinders.Binders.DefaultBinder = new CustomModelBinder(); 

CustomModelBinder:

public class CustomModelBinder2 : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var modelType = bindingContext.ModelType; 
     if (modelType.IsAbstract) 
     { 
      var modelTypeValue = controllerContext.Controller.ValueProvider.GetValue("ModelTypeName"); 
      if (modelTypeValue == null) 
       throw new Exception("View does not contain ModelTypeName"); 

      var modelTypeName = modelTypeValue.AttemptedValue; 

      var type = modelType.Assembly.GetTypes().SingleOrDefault(x => x.IsSubclassOf(modelType) && x.Name == modelTypeName); 

      if (type != null) 
      { 
       var instance= bindingContext.Model ?? base.CreateModel(controllerContext, bindingContext, type); 
       bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => instance, type); 
      } 
     } 
     return base.BindModel(controllerContext, bindingContext); 
    } 
} 
+0

यह एक उपयोगी उत्तर है, लेकिन सिर्फ इसे लागू करने वाले किसी के लिए, मुझे संदेह है कि यहां एक सुरक्षा जोखिम हो सकता है यदि ग्राहक एक हानिकारक लेकिन वैध प्रकार के नाम को हानिकारक कन्स्ट्रक्टर के साथ भेजता है। सही? –

+0

यह भी देखें http://stackoverflow.com/questions/7222533/polymorphic-model-binding/9813472#9813472 –

+0

@ uosɐs: केवल मामले में एमवीसी उप-वर्ग में मैप करने का प्रयास कर रहा है (देखें 'ISSubclassOf (...) ') नियंत्रक कार्रवाई हस्ताक्षर में उपयोग की जाने वाली अपेक्षित अमूर्त कक्षा का, या नियंत्रक कार्रवाई हस्ताक्षर वस्तुओं में से एक 'बाल गुण। और फिर इसे "हानिकारक" कन्स्ट्रक्टर होना चाहिए। मैं इस कोड का उपयोग करने के बारे में सोच रहा हूँ। क्या आप ऐसे सुरक्षा जोखिम का उदाहरण दे सकते हैं? –

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