2010-11-24 16 views
9

में कस्टम सत्यापन विशेषता से सदस्य नाम सेट करने में असमर्थ I ValidationAttribute subclassing द्वारा एक कस्टम सत्यापन विशेषता बनाई है। विशेषता वर्ग के स्तर पर मेरे व्यूमोडेल पर लागू होती है क्योंकि इसे एक से अधिक संपत्तियों को सत्यापित करने की आवश्यकता होती है।एमवीसी 2

मैं

protected override ValidationResult IsValid(object value, ValidationContext validationContext) 

अधिभावी कर रहा हूँ और लौटने:

new ValidationResult("Always Fail", new List<string> { "DateOfBirth" }); 
सभी मामलों में जहां DateOfBirth मेरे विचार मॉडल पर संपत्ति में से एक है में

जब मैं अपना आवेदन चलाता हूं, तो मैं इसे हिट कर देख सकता हूं। ModelState.IsValid सही ढंग से गलत पर सेट है लेकिन जब मैं मॉडलस्टेट सामग्री का निरीक्षण करता हूं, तो मुझे लगता है कि संपत्ति दिनांकऑफबर्थ में कोई त्रुटि नहीं है। इसके बजाय मेरे पास शून्य के मान के साथ एक खाली स्ट्रिंग कुंजी है और एक अपवाद है जिसमें मैंने अपनी सत्यापन विशेषता में निर्दिष्ट स्ट्रिंग है।

इसके परिणामस्वरूप ValidationMessageFor का उपयोग करते समय मेरे UI में कोई त्रुटि संदेश प्रदर्शित नहीं किया जा रहा है। अगर मैं प्रमाणीकरणसमरी का उपयोग करता हूं, तो मैं त्रुटि देख सकता हूं। ऐसा इसलिए है क्योंकि यह किसी संपत्ति से जुड़ा नहीं है।

ऐसा लगता है कि यह इस तथ्य को अनदेखा कर रहा है कि मैंने सत्यापन परिणाम में सदस्य नाम निर्दिष्ट किया है।

यह क्यों है और मैं इसे कैसे ठीक करूं?

उदाहरण कोड के रूप में अनुरोध:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 
    public class ExampleValidationAttribute : ValidationAttribute 
    { 
     protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
     { 
      // note that I will be doing complex validation of multiple properties when complete so this is why it is a class level attribute 
      return new ValidationResult("Always Fail", new List<string> { "DateOfBirth" }); 
     } 
    } 

    [ExampleValidation] 
    public class ExampleViewModel 
    { 
     public string DateOfBirth { get; set; } 
    } 

उत्तर

2

मैं एक आसान तरीका के इस व्यवहार को ठीक बारे में पता नहीं कर रहा हूँ। यही कारण है कि मैं डेटा एनोटेशन से नफरत करता हूं। FluentValidation के साथ एक ही कर केक का एक शांति होगा:

public class ExampleViewModelValidator: AbstractValidator<ExampleViewModel> 
{ 
    public ExampleViewModelValidator() 
    { 
     RuleFor(x => x.EndDate) 
      .GreaterThan(x => x.StartDate) 
      .WithMessage("end date must be after start date"); 
    } 
} 

FluentValidation महान support and integration with ASP.NET MVC है।

+3

धन्यवाद करने में मदद कर सकता है। तो एमवीसी टीम ValidationResult कक्षा का पुन: उपयोग कर रही है लेकिन संपत्तियों में से एक को पूरी तरह से अनदेखा कर रही है? पूरी तरह से मैं एमवीसी टीम के आउटपुट से बेहद प्रभावित हूं लेकिन यह बहुत खराब है। मैंने इसे अभी एमवीसी 3/.NET4 में चेक किया है और यह अभी भी वही है। –

-1

आप त्रुटिसंदेश गुण सेट करने की जरूरत है, उदाहरण के लिए इतना:

public class DOBValidAttribute : ValidationAttribute 
{ 
    private static string _errorMessage = "Date of birth is a required field."; 

    public DOBValidAttribute() : base(_errorMessage) 
    { 

    } 
//etc......overriding IsValid.... 
+0

त्रुटि संदेश सेट किया जा रहा है और जैसा ऊपर बताया गया है ठीक है। मुद्दा सदस्य नाम के साथ है जो मॉडलस्टेट में कुंजी को मैप करना चाहिए। –

+0

क्या आप अपना कोड पोस्ट कर सकते हैं, तो यह हमारे लिए – ozz

13

सभी को नमस्कार।

अभी भी समाधान की तलाश है?

मैंने आज भी यही समस्या हल कर दी है। आपको कस्टम सत्यापन विशेषता बनाना है जो 2 तिथियों (नीचे उदाहरण) को मान्य करेगा। फिर आपको एडाप्टर (सत्यापनकर्ता) की आवश्यकता है जो आपके कस्टम विशेषता के साथ मॉडल को मान्य करेगा। और आखिरी बात विशेषता के साथ बाध्यकारी एडाप्टर है। हो सकता है कि कुछ उदाहरण यह बेहतर समझा जाएगा की तुलना में मेरे :)

ये हम चले:

DateCompareAttribute.cs:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] 
public class DateCompareAttribute : ValidationAttribute 
{ 
    public enum Operations 
    { 
     Equals,    
     LesserThan, 
     GreaterThan, 
     LesserOrEquals, 
     GreaterOrEquals, 
     NotEquals 
    }; 

    private string _From; 
    private string _To; 
    private PropertyInfo _FromPropertyInfo; 
    private PropertyInfo _ToPropertyInfo; 
    private Operations _Operation; 

    public string MemberName 
    { 
     get 
     { 
      return _From; 
     } 
    } 

    public DateCompareAttribute(string from, string to, Operations operation) 
    { 
     _From = from; 
     _To = to; 
     _Operation = operation; 

     //gets the error message for the operation from resource file 
     ErrorMessageResourceName = "DateCompare" + operation.ToString(); 
     ErrorMessageResourceType = typeof(ValidationStrings); 
    } 

    public override bool IsValid(object value) 
    { 
     Type type = value.GetType(); 

     _FromPropertyInfo = type.GetProperty(_From); 
     _ToPropertyInfo = type.GetProperty(_To); 

     //gets the values of 2 dates from model (using reflection) 
     DateTime? from = (DateTime?)_FromPropertyInfo.GetValue(value, null); 
     DateTime? to = (DateTime?)_ToPropertyInfo.GetValue(value, null); 

     //compare dates 
     if ((from != null) && (to != null)) 
     { 
      int result = from.Value.CompareTo(to.Value); 

      switch (_Operation) 
      { 
       case Operations.LesserThan: 
        return result == -1; 
       case Operations.LesserOrEquals: 
        return result <= 0; 
       case Operations.Equals: 
        return result == 0; 
       case Operations.NotEquals: 
        return result != 0; 
       case Operations.GreaterOrEquals: 
        return result >= 0; 
       case Operations.GreaterThan: 
        return result == 1; 
      } 
     } 

     return true; 
    } 

    public override string FormatErrorMessage(string name) 
    { 
     DisplayNameAttribute aFrom = (DisplayNameAttribute)_FromPropertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault(); 
     DisplayNameAttribute aTo = (DisplayNameAttribute)_ToPropertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault(); 

     return string.Format(ErrorMessageString, 
      !string.IsNullOrWhiteSpace(aFrom.DisplayName) ? aFrom.DisplayName : _From, 
      !string.IsNullOrWhiteSpace(aTo.DisplayName) ? aTo.DisplayName : _To); 
    } 
} 

DateCompareAttributeAdapter.cs:

public class DateCompareAttributeAdapter : DataAnnotationsModelValidator<DateCompareAttribute> 
{ 
    public DateCompareAttributeAdapter(ModelMetadata metadata, ControllerContext context, DateCompareAttribute attribute) 
     : base(metadata, context, attribute) { 
    } 

    public override IEnumerable<ModelValidationResult> Validate(object container) 
    { 
     if (!Attribute.IsValid(Metadata.Model)) 
     { 
      yield return new ModelValidationResult 
      { 
       Message = ErrorMessage, 
       MemberName = Attribute.MemberName 
      }; 
     } 
    } 
} 

Global.asax:

protected void Application_Start() 
{ 
    // ... 
    DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(DateCompareAttribute), typeof(DateCompareAttributeAdapter)); 
} 

कस्टम व्यू मॉडेल।सीएस:

[DateCompare("StartDateTime", "EndDateTime", DateCompareAttribute.Operations.LesserOrEquals)] 
public class CustomViewModel 
{ 
    // Properties... 

    public DateTime? StartDateTime 
    { 
     get; 
     set; 
    } 

    public DateTime? EndDateTime 
    { 
     get; 
     set; 
    } 
} 
+0

अच्छा काम। एमवीसी 3 में आप validationContext.ObjectInstance प्रॉपर्टी का उपयोग कर संपत्ति स्तर विशेषता से अन्य गुणों तक पहुंच सकते हैं, जो मेरे लिए अच्छा काम करता है। आप यहां एक उदाहरण देख सकते हैं: http://favcode.net/browse/condition_validation_with_custom_validationattribute_using_.net_4.0_data_annotations_in_mvc3 –

+2

गंभीरता से, यह समाधान है। – abx78

+1

इस सत्यापन को चलाने के लिए किसी भी तरह से क्लाइंट पक्ष चलाने के लिए? – Donuts

0

सत्यापन परिणाम लौटने पर दो पैरामीटर कन्स्ट्रक्टर का उपयोग करें। इसे संदर्भ के साथ एक सरणी पास करें। मेम्बरनाम एकमात्र मान के रूप में। उम्मीद है कि यह

<AttributeUsage(AttributeTargets.Property Or AttributeTargets.Field, AllowMultiple:=False)> 


Public Class NonNegativeAttribute 
Inherits ValidationAttribute 
Public Sub New() 


End Sub 
Protected Overrides Function IsValid(num As Object, context As ValidationContext) As ValidationResult 
    Dim t = num.GetType() 
    If (t.IsValueType AndAlso Not t.IsAssignableFrom(GetType(String))) Then 

     If ((num >= 0)) Then 
      Return ValidationResult.Success 
     End If 
     Return New ValidationResult(context.MemberName & " must be a positive number",  New String() {context.MemberName}) 

    End If 

    Throw New ValidationException(t.FullName + " is not a valid type. Must be a number") 
End Function 

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