कहें कि मेरे पास एक उत्पाद मॉडल है, उत्पाद मॉडल में उत्पादसूब टाइप (सार) की एक संपत्ति है और हमारे पास दो ठोस कार्यान्वयन शर्ट और पैंट हैं।एमवीसी 3 मॉडल एक उप प्रकार (सार कक्षा या इंटरफेस) बाध्यकारी
यहाँ स्रोत है:
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public decimal? Price { get; set; }
[Required]
public int? ProductType { get; set; }
public ProductTypeBase SubProduct { get; set; }
}
public abstract class ProductTypeBase { }
public class Shirt : ProductTypeBase
{
[Required]
public string Color { get; set; }
public bool HasSleeves { get; set; }
}
public class Pants : ProductTypeBase
{
[Required]
public string Color { get; set; }
[Required]
public string Size { get; set; }
}
मेरी UI में, उपयोगकर्ता एक ड्रॉपडाउन है, वे उत्पाद के प्रकार का चयन कर सकते हैं और इनपुट तत्वों सही उत्पाद के प्रकार के अनुसार प्रदर्शित होते हैं। मेरे पास यह सब पता लगाया गया है (अजाक्स का उपयोग ड्रॉपडाउन परिवर्तन पर मिलता है, आंशिक/संपादक टेम्पलेट लौटाता है और तदनुसार jquery सत्यापन को फिर से सेटअप करता है)।
अगला मैंने ProductTypeBase के लिए कस्टम मॉडल बाइंडर बनाया।
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ProductTypeBase subType = null;
var productType = (int)bindingContext.ValueProvider.GetValue("ProductType").ConvertTo(typeof(int));
if (productType == 1)
{
var shirt = new Shirt();
shirt.Color = (string)bindingContext.ValueProvider.GetValue("SubProduct.Color").ConvertTo(typeof(string));
shirt.HasSleeves = (bool)bindingContext.ValueProvider.GetValue("SubProduct.HasSleeves").ConvertTo(typeof(bool));
subType = shirt;
}
else if (productType == 2)
{
var pants = new Pants();
pants.Size = (string)bindingContext.ValueProvider.GetValue("SubProduct.Size").ConvertTo(typeof(string));
pants.Color = (string)bindingContext.ValueProvider.GetValue("SubProduct.Color").ConvertTo(typeof(string));
subType = pants;
}
return subType;
}
}
यह सही ढंग से मूल्यों बांधता है और अधिकांश भाग के लिए काम करता है को छोड़कर मैं सर्वर साइड सत्यापन खो देते हैं। तो एक कूबड़ पर है कि मैं यह कर रहा हूं गलत तरीके से मैं कुछ अधिक खोज किया था और डैरिन दिमित्रोव से इस जवाब में आए:
ASP.NET MVC 2 - Binding To Abstract Model
तो मैं केवल CreateModel ओवरराइड करने के लिए मॉडल बांधने की मशीन बंद है, लेकिन अब ऐसा नहीं होता मूल्यों को बांधें।
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
ProductTypeBase subType = null;
var productType = (int)bindingContext.ValueProvider.GetValue("ProductType").ConvertTo(typeof(int));
if (productType == 1)
{
subType = new Shirt();
}
else if (productType == 2)
{
subType = new Pants();
}
return subType;
}
हालांकि MVC 3 src कदम है, यह BindProperties में की तरह लगता है, GetFilteredModelProperties एक खाली परिणाम देता है, और मुझे लगता है कि क्योंकि bindingcontext मॉडल ProductTypeBase के लिए सेट है जो किसी भी गुण नहीं है।
क्या कोई यह बता सकता है कि मैं क्या गलत कर रहा हूं? ऐसा प्रतीत नहीं होता है कि यह मुश्किल होना चाहिए। मुझे यकीन है कि मुझे कुछ आसान याद आ रही है ... उत्पाद मॉडल में सबप्रॉडक्ट प्रॉपर्टी रखने के बजाय शर्ट और पैंट के लिए अलग-अलग गुण होने के बजाय मेरे पास एक और विकल्प है। ये केवल व्यू/फॉर्म मॉडल हैं, इसलिए मुझे लगता है कि यह काम करेगा, लेकिन अगर मौजूदा कुछ भी हो रहा है तो यह समझने के लिए मौजूदा दृष्टिकोण प्राप्त करना चाहते हैं ...
किसी भी मदद के लिए धन्यवाद!
अद्यतन:
मैं यह स्पष्ट नहीं था, लेकिन कस्टम मॉडल बांधने की मशीन मैं कहा, से DefaultModelBinder
उत्तर
स्थापना ModelMetadata और मॉडल लापता टुकड़ा था इनहेरिट करती है। धन्यवाद मनस!
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
if (modelType.Equals(typeof(ProductTypeBase))) {
Type instantiationType = null;
var productType = (int)bindingContext.ValueProvider.GetValue("ProductType").ConvertTo(typeof(int));
if (productType == 1) {
instantiationType = typeof(Shirt);
}
else if (productType == 2) {
instantiationType = typeof(Pants);
}
var obj = Activator.CreateInstance(instantiationType);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, instantiationType);
bindingContext.ModelMetadata.Model = obj;
return obj;
}
return base.CreateModel(controllerContext, bindingContext, modelType);
}
बिल्कुल सही, मॉडलमेटाडेटा और मॉडल को बनाने में मॉडल को याद करने वाला टुकड़ा था, धन्यवाद! –
मेरे पास विरासत और व्युत्पन्न प्रकार के साथ एक बहुत ही समान समस्या थी और उपरोक्त मॉडल बाइंडर कोड ने चाल की थी। चीयर्स! –
धन्यवाद! मैं अंततः इस समाधान का सहारा लेने के लिए लगभग तीन दिन कोशिश कर रहा हूं, हालांकि मेरी समस्या कुछ अलग थी। –