2012-01-18 11 views
12

मुझे पता है कि मॉडल पर सेट की गई [आवश्यक] विशेषता को ओवरराइड करना संभव है या नहीं। मुझे यकीन है कि इस समस्या का कोई आसान समाधान है, कोई भी लेने वाला?क्या मॉडल में किसी संपत्ति पर आवश्यक विशेषता को ओवरराइड करना संभव है?

+2

परिभाषित करें "ओवरराइड"। क्या आपका मतलब है कि आपके मॉडल का एक उप-वर्ग बनाना जहां उस संपत्ति की आवश्यकता नहीं है, या क्या आपका मतलब है कि एक विशिष्ट नियंत्रक कार्रवाई नहीं करनी चाहिए यदि कोई आवश्यक फ़ील्ड प्रदान नहीं किया जाता है? क्या आप क्लाइंट-साइड सत्यापन या सिर्फ सर्वर पक्ष के बारे में चिंतित हैं? – StriplingWarrior

उत्तर

16

आप क्या कर रहे हैं इस पर निर्भर करता है। यदि आप उप-वर्ग के साथ काम कर रहे हैं, तो मॉडल के आधार पर आवश्यक विशेषता के साथ मॉडल का उपयोग करके, आप यह कर सकते हैं:

new कीवर्ड के साथ संपत्ति को फिर से ओवरराइड करने के बजाय, इसे फिर से परिभाषित करें।

public class BaseModel 
{ 
    [Required] 
    public string RequiredProperty { get; set; } 
} 


public class DerivativeModel : BaseModel 
{ 
    new public string RequiredProperty { get; set; } 

} 

आप बस बाँध या एक मॉडल को मान्य है, लेकिन अपने नियंत्रक में आवश्यक संपत्ति को छोड़ना चाहते हैं, तो आप की तरह कुछ कर सकते हैं:

public ActionResult SomeAction() 
{ 
    var model = new BaseModel(); 

    if (TryUpdateModel(model, null, null, new[] { "RequiredProperty" })) // fourth parameter is an array of properties (by name) that are excluded 
    { 
      // updated and validated correctly! 
      return View(model); 
    } 
    // failed validation 
    return View(model); 
} 
+0

बिल्कुल सही, धन्यवाद! –

+0

यदि आप अभिभावक वर्ग फ़ील्ड पर निर्भर करते हैं, तो आप 'आधार' से सेट करना और प्राप्त करना चाहते हैं: 'वापसी {वापसी आधार। आवश्यक प्रॉपर्टी; } सेट {value = base.RequiredProperty;} ' – pauloya

+2

विषम लेकिन यह मेरे लिए काम नहीं करता है। मेरे पास एक विशेषता है [रेंज (0, 99 99 99)] और बाल वर्ग में [रेंज (0,2000)] है लेकिन सत्यापन – Nick

4

आप एक कस्टम मान्यता विशेषता का उपयोग कर सकते हैं (यह हो सकता है RequiredAttribute से प्राप्त किया जा):

public class RequiredExAttribute : RequiredAttribute 
    { 
     public bool UseRequiredAttribute { get; protected set; } 
     public RequiredExAttribute(bool IsRequired) 
     { 
      UseRequiredAttribute = IsRequired; 
     } 
     public override bool IsValid(object value) 
     { 
      if (UseRequiredAttribute) 
       return base.IsValid(value); 
      else 
      { 
       return true; 
      } 
     } 

     public override bool RequiresValidationContext 
     { 
      get 
      { 
       return UseRequiredAttribute; 
      } 
     } 
    } 

    public class RequiredExAttributeAdapter : RequiredAttributeAdapter 
    { 
     public RequiredExAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredExAttribute attribute) 
      : base(metadata, context, attribute) { } 

     public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() 
     { 
      if (((RequiredExAttribute)Attribute).UseRequiredAttribute)// required -> return normal required rules 
       return base.GetClientValidationRules(); 
      else// not required -> return empty rules list 
       return new List<ModelClientValidationRule>(); 
     } 
    } 

और फिर Application_Start में यह regester इस कोड लाइन का उपयोग:

, तो आप ऐसा
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredExAttribute), typeof(RequiredExAttributeAdapter)); 
9

@HackedByChinese विधि ठीक है, लेकिन यह एक समस्या

public class BaseModel 
{ 
    [Required] 
    public string RequiredProperty { get; set; } 
} 

public class DerivativeModel : BaseModel 
{ 
    new public string RequiredProperty { get; set; } 
} 
शामिल

इस कोड को आप ModelState में एक मान्यता त्रुटि दिखा सकते हैं, भले ही आप फार्म पर DerivativeModel उपयोग करते हैं, या तो काम नहीं करता है override या अधिभावी द्वारा Required विशेषता को नष्ट नहीं यह renewin कर सकते हैं, तो मैं एक समाधान

public class BaseModel 
{ 
    public virtual string RequiredProperty { get; set; } 
} 

public class DerivativeModel : BaseModel 
{ 
    [Required] 
    public override string RequiredProperty { get; set; } 
} 

public class DerivativeModel2 : BaseModel 
{ 
    [Range(1, 10)] 
    public override string RequiredProperty { get; set; } 
} 

मुझे कोई मान्यता गुण और व्युत्पन्न वर्ग के साथ एक बेस मॉडल की एक किसी प्रकार के लिए आया था es

+0

मॉडलस्टेट सत्यापन त्रुटि के बारे में आपको धन्यवाद, मैंने सोचा कि मैं कुछ गलत कर रहा हूं – RMazitov

1

मैंने महमूद के जवाब की कोशिश की, लेकिन यह कुछ बदलावों के बिना मेरे लिए काम नहीं किया। इसे एक उत्तर के रूप में जोड़ना ताकि मैं कोड दे सकूं जो किसी और की मदद करता है, लेकिन महमूद हबौबाती को पूरा श्रेय - मैंने आपका जवाब उभारा है।

मेरी स्थिति में मेरे पास डीबीजीओोग्राफी संपत्ति के साथ एक मूल डीटीओ कक्षा थी जो एक एमवीसी परियोजना के लिए आवश्यक था जिसने डीबीजीओोग्राफी प्रकार के लिए एक कस्टम संपादक टेम्पलेट और डिस्प्ले टेम्पलेट का उपयोग किया था। लेकिन एक वेब एपीआई नियंत्रक के लिए एक मॉडल पोस्ट करने के लिए मैं उस डीटीओ के उप-वर्ग में अक्षांश/देशांतर फ़ील्ड जोड़ना चाहता था, जिसका उपयोग डीबीजीओग्राफी संपत्ति पर मूल्य निर्धारित करने के लिए डीबीजीगोग्राफी कक्षा का एक उदाहरण बनाने और सेट करने के लिए किया जाएगा। समस्या यह थी कि, मैं केवल उप-वर्ग पर डीबीजीओग्राफी प्रॉपर्टी की आवश्यकता नहीं कर सका।

जब महमूद के दृष्टिकोण का उपयोग करके कन्स्ट्रक्टर में बुलियन मूल्य पारित किया गया था, तो यह मेरे लिए डिफ़ॉल्ट मान को ओवरराइड नहीं लग रहा था। ऐसा इसलिए हो सकता है क्योंकि मैं वेब एपीआई का उपयोग कर रहा हूं और कारखाने के दृष्टिकोण का उपयोग करके विशेषता दर्ज कर रहा हूं, जैसे कि ग्लोबल.एक्सएक्स में।सीएस Application_Start विधि):

using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.Web.Mvc; 
... 
public class RequiredExAttribute : RequiredAttribute 
{ 
    public bool IsRequired { get; set; } 

    public override bool IsValid(object value) 
    { 
     if (IsRequired) 
      return base.IsValid(value); 
     else 
     { 
      return true; 
     } 
    } 

    public override bool RequiresValidationContext 
    { 
     get 
     { 
      return IsRequired; 
     } 
    } 
} 

public class RequiredExAttributeAdapter : RequiredAttributeAdapter 
{ 
    public RequiredExAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredExAttribute attribute) 
     : base(metadata, context, attribute) { } 

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() 
    { 
     if (((RequiredExAttribute)Attribute).IsRequired)// required -> return normal required rules 
      return base.GetClientValidationRules(); 
     else// not required -> return empty rules list 
      return new List<ModelClientValidationRule>(); 
    } 
} 

बेस कक्षा:

[RequiredEx(IsRequired = true)] 
public virtual DbGeography Location { get; set; } 

उपवर्ग:

DataAnnotationsModelValidationFactory factory = (p, a) => new DataAnnotationsModelValidator(
    new List<ModelValidatorProvider>(), new RequiredExAttribute() 
); 

DataAnnotationsModelValidatorProvider provider = new DataAnnotationsModelValidatorProvider(); 
provider.RegisterAdapterFactory(typeof(RequiredExAttribute), factory); 

मैं इस के लिए विशेषता वर्ग बदलना पड़ा

[RequiredEx(IsRequired = false)] 
public override DbGeography Location { get; set; } 

[Required] 
public decimal Latitude { get; set; } 

[Required] 
public decimal Longitude { get; set; } 

ध्यान दें, मैंने महमूद के ऊपर की तरह ही एक ही विधि का इस्तेमाल किया मेरी MVC परियोजना में विशेषता के पंजीकरण के लिए:

DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredExAttribute), typeof(RequiredExAttributeAdapter)); 
1

हाँ, यह संभव MetadataType वर्ग, उदा उपयोग कर रहा है:

[MetadataType(typeof(Base.Metadata))] 
public class Base 
{  
    public string RequiredProperty { get; set; } 

    public class Metadata 
    { 
     [Required] 
     public string RequiredProperty { get; set; } 
    } 
} 

[MetadataType(typeof(Derived.Metadata))] 
public class Derived : Base 
{ 
    public new class Metadata 
    { 
    } 
} 

और यह परीक्षण:

var type = typeof(Derived); 

var metadataType = typeof(Derived.Metadata); 

var provider = new AssociatedMetadataTypeTypeDescriptionProvider(type, metadataType); 

TypeDescriptor.AddProviderTransparent(provider, type); 

var instance = new Derived(); 

var results = new List<ValidationResult>(); 

Validator.TryValidateObject(instance, 
    new ValidationContext(instance), 
    results, 
    true); 

Debug.Assert(results.Count == 0); 
संबंधित मुद्दे