2012-03-21 12 views
14

के साथ क्लाइंट पर चेकबॉक्स मान्य करें मैं फ़्लुएंट वैधता का उपयोग कर क्लाइंट पर चेक बॉक्स चेक किए जाने पर सत्यापित करने की कोशिश कर रहा हूं। मैं इसे हमारे जीवन के लिए नहीं समझ सकता।FluentValidation/MVC 3

क्या यह अविभाज्य सत्यापन का उपयोग करके किया जा सकता है?

public class MyViewModelValidator : AbstractValidator<MyViewModel> 
{ 
    public MyViewModelValidator() 
    { 
     RuleFor(x => x.IsChecked).Equal(true).WithMessage("Please check this checkbox"); 
    } 
} 

और एक नियंत्रक:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(); 
    } 

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

एक इसी दृश्य के साथ: निम्नलिखित सत्यापनकर्ता साथ

[Validator(typeof(MyViewModelValidator))] 
public class MyViewModel 
{ 
    public bool IsChecked { get; set; } 
} 

:

उत्तर

24

मान लेते हैं तो आपको निम्न मॉडल है कि चलो

@model MyViewModel 
@using (Html.BeginForm()) 
{ 
    @Html.LabelFor(x => x.IsChecked) 
    @Html.CheckBoxFor(x => x.IsChecked) 
    @Html.ValidationMessageFor(x => x.IsChecked) 
    <button type="submit">OK</button> 
} 

और Global.asax में आप धाराप्रवाह सत्यापन मॉडल सत्यापनकर्ता प्रदाता पंजीकृत किया है:

FluentValidationModelValidatorProvider.Configure(); 

अब तक हम सर्वर साइड सत्यापन और चल ठीक है। अच्छी बात है। यह हमेशा पहला हिस्सा है जिसे हमें सेटअप करना होगा। मैंने लोगों को क्लाइंट साइड सत्यापन करने पर बहुत अधिक ध्यान केंद्रित किया है कि वे सर्वर साइड सत्यापन करना भूल जाते हैं और जब आप जावास्क्रिप्ट को अक्षम करते हैं (या यदि आप खराब इरादों वाले उपयोगकर्ता पर ठोकर खाते हैं तो भी बदतर), अच्छी तरह से, बुरी चीजें होती हैं। अब तक हम आश्वस्त हैं क्योंकि हम जानते हैं कि क्लाइंट पर कुछ खराब हो जाने पर भी हमारा डोमेन सर्वर साइड सत्यापन से सुरक्षित है।


तो चलिए अब ग्राहक सत्यापन की देखभाल करते हैं। बॉक्स के बाहर FluentValidation.NET EqualTo सत्यापनकर्ता के लिए स्वचालित क्लाइंट सत्यापन का समर्थन करता है लेकिन जब किसी अन्य संपत्ति मान के विरुद्ध तुलना करता है जो [Compare] डेटा एनोटेशन के बराबर है।

लेकिन हमारे मामले में हम एक निश्चित मूल्य के खिलाफ तुलना कर रहे हैं। इसलिए हमें बॉक्स से क्लाइंट साइड वाइल्डेशन नहीं मिलता है। और जब हमें बॉक्स से कुछ नहीं मिलता है, तो हमें इसे बॉक्स में रखना होगा।

तो हम एक कस्टम FluentValidationPropertyValidator को परिभाषित करने से शुरू:

public class EqualToValueFluentValidationPropertyValidator : FluentValidationPropertyValidator 
{ 
    public EqualToValueFluentValidationPropertyValidator(ModelMetadata metadata, ControllerContext controllerContext, PropertyRule rule, IPropertyValidator validator) 
     : base(metadata, controllerContext, rule, validator) 
    { 
    } 

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() 
    { 
     if (!this.ShouldGenerateClientSideRules()) 
     { 
      yield break; 
     } 
     var validator = (EqualValidator)Validator; 

     var errorMessage = new MessageFormatter() 
      .AppendPropertyName(Rule.GetDisplayName()) 
      .AppendArgument("ValueToCompare", validator.ValueToCompare) 
      .BuildMessage(validator.ErrorMessageSource.GetString()); 

     var rule = new ModelClientValidationRule(); 
     rule.ErrorMessage = errorMessage; 
     rule.ValidationType = "equaltovalue"; 
     rule.ValidationParameters["valuetocompare"] = validator.ValueToCompare; 
     yield return rule; 
    } 
} 

कि हम Application_Start में रजिस्टर करने के लिए जा रहे हैं:

FluentValidationModelValidatorProvider.Configure(provider => 
{ 
    provider.AddImplicitRequiredValidator = false; 
    provider.Add(typeof(EqualValidator), (metadata, context, description, validator) => new EqualToValueFluentValidationPropertyValidator(metadata, context, description, validator)); 
}); 

अब तक हम EqualValidator साथ हमारे कस्टम FluentValidationPropertyValidator संबद्ध कर दिया है।

अंतिम भाग एक कस्टम एडाप्टर लिखना है:

(function ($) { 
    $.validator.unobtrusive.adapters.add('equaltovalue', ['valuetocompare'], function (options) { 
     options.rules['equaltovalue'] = options.params; 
     if (options.message != null) { 
      options.messages['equaltovalue'] = options.message; 
     } 
    }); 

    $.validator.addMethod('equaltovalue', function (value, element, params) { 
     if ($(element).is(':checkbox')) { 
      if ($(element).is(':checked')) { 
       return value.toLowerCase() === 'true'; 
      } else { 
       return value.toLowerCase() === 'false'; 
      } 
     } 
     return params.valuetocompare.toLowerCase() === value.toLowerCase(); 
    }); 
})(jQuery);  

और है कि यह काफी है। अब सिर्फ़ ग्राहक स्क्रिप्ट शामिल करने के लिए है:

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/customadapter.js")" type="text/javascript"></script> 
+0

धन्यवाद का उपयोग करने की जरूरत नहीं है, यह बहुत अच्छा है। लेकिन मुझे इसके साथ लाइनों को बदलना पड़ा: [वापसी मूल्य .toLowerCase() === ...] से: [वापसी params.valuetocompare.toLowerCase() === ...] – cryss

+0

http: // stackoverflow देखें। कॉम/प्रश्न/21345078/फ़्लुएंटिडेशन-वैध-चेकबॉक्स-और-पासवर्ड-ऑन-द-क्लाइंट-साथ-बराबरडालिडेटो किसी समस्या के साथ एक समाधान के साथ एक और समान वैधकर्ता मौजूद है (उदाहरण के लिए पासवर्ड की पुष्टि करें)। – Ted

4

मैं डैरिन दिमित्रोव का जवाब चाहते हैं, लेकिन अगर आप इसे जल्दी से ऐसा करने के लिए, चाहते हैं यहाँ मेरी वैकल्पिक तरीका है।

अपने मॉडल में एक अतिरिक्त संपत्ति बनाएं, उदा।:

public bool ValidationTrue { get; set; } 

और मॉडल की contructor में true लिए अपने मूल्य निर्धारित किया है।

अनुरोध भर में मूल्य को बचाने के लिए अपने दृश्य में उपयोग करें:

@Html.HiddenFor(x => x.ValidationTrue) 

अब इस तरह की एक सत्यापन नियम जोड़ें:

public class MyViewModelValidator : AbstractValidator<MyViewModel> 
{ 
    public MyViewModelValidator() 
    { 
     RuleFor(x => x.ValidationTrue) 
      .Equal(true); // check it for security reasons, if someone has edited it in the source of the page 

     RuleFor(x => x.HasToBeChecked) 
      .Equal(x => x.ValidationTrue) // HasToBeChecked has to have the same value as ValidationTrue (which is always true) 
      .WithMessage("Required"); 
    } 
} 

सत्यापन विनीत सत्यापनकर्ता बाहर के द्वारा समर्थित है कि -डिब्बा।

1

मैं एएसपी.नेट एमवीसी 5 में कोडिंग कर रहा हूं और डारिन का कोड संदर्भ मूल्यों पर एक जावास्क्रिप्ट त्रुटि उत्पन्न करता है। लोअरकेस() जब एक चेकबॉक्स शामिल होता है। एक और मुद्दा यह है कि यह कोड क्लाइंट साइड समानता तुलना को दो गुणों के बीच अमान्य करता है। यह एक शाब्दिक मूल्य के मुकाबले तुलना करने पर ही काम करता है ... शायद यह उनका इरादा हो सकता है, लेकिन मुझे दोनों स्थितियों के लिए काम करने की ज़रूरत है:

यहां एक संभावित कामकाज है, जिसमें डारिन के उत्तर में केवल दो बदलाव शामिल हैं:

सबसे पहले, मैंने निम्नलिखित के साथ जावास्क्रिप्ट फ़ंक्शन को अपडेट किया।

$.validator.addMethod('equaltovalue', function (value, element, params) { 
    if ($(element).is(':checkbox')) { 
     value = $(element).is(':checked') ? "true" : "false"; 
    } 
    return params.valuetocompare.toLowerCase() === value.toLowerCase(); 
}); 

दूसरे, मैं निम्नलिखित के साथ EqualToValueFluentValidationPropertyValidator अद्यतन:

public class EqualToValueFluentValidationPropertyValidator : FluentValidationPropertyValidator 
{ 
    EqualValidator EqualValidator 
    { 
     get { return (EqualValidator)Validator; } 
    } 

    public EqualToValueFluentValidationPropertyValidator(ModelMetadata metadata, ControllerContext controllerContext, PropertyRule rule, IPropertyValidator validator) : base(metadata, controllerContext, rule, validator) { 
     ShouldValidate = false; 
    } 

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() { 
     if (!ShouldGenerateClientSideRules()) yield break; 

     var propertyToCompare = EqualValidator.MemberToCompare as PropertyInfo; 
     if(propertyToCompare != null) { 
      // If propertyToCompare is not null then we're comparing to another property. 
      // If propertyToCompare is null then we're either comparing against a literal value, a field or a method call. 
      // We only care about property comparisons in this case. 

      var comparisonDisplayName = 
       ValidatorOptions.DisplayNameResolver(Rule.TypeToValidate, propertyToCompare, null) 
       ?? propertyToCompare.Name.SplitPascalCase(); 

      var formatter = new MessageFormatter() 
       .AppendPropertyName(Rule.GetDisplayName()) 
       .AppendArgument("ComparisonValue", comparisonDisplayName); 


      string message = formatter.BuildMessage(EqualValidator.ErrorMessageSource.GetString()); 
      yield return new ModelClientValidationEqualToRule(message, CompareAttribute.FormatPropertyForClientValidation(propertyToCompare.Name)) ; 
     } 
     else 
     { 
      var validator = (EqualValidator)Validator; 

      var errorMessage = new MessageFormatter() 
       .AppendPropertyName(Rule.GetDisplayName()) 
       .AppendArgument("ValueToCompare", validator.ValueToCompare) 
       .BuildMessage(validator.ErrorMessageSource.GetString()); 

      var rule = new ModelClientValidationRule(); 
      rule.ErrorMessage = errorMessage; 
      rule.ValidationType = "equaltovalue"; 
      rule.ValidationParameters["valuetocompare"] = validator.ValueToCompare; 
      yield return rule; 
     } 
    } 
} 

इस कोड fluentvalidation स्रोत में EqualToFluentValidationPropertyValidator आंतरिक वर्ग से नकल किया गया था, और मैं किसी और के बाद डैरिन के तर्क गयी। यह क्लाइंट-साइड सत्यापन को संपत्ति तुलना के साथ-साथ मूल्य तुलना के लिए काम करने की अनुमति देता है ... मुझे यकीन नहीं है कि यह एक अच्छा तरीका है क्योंकि आप मूल रूप से अंतर्निहित समानता वैधता को ओवरराइड कर रहे हैं और यह भविष्य में रिलीज़ में टूट सकता है धाराप्रवाह सत्यापन के .... लेकिन डारिन के जवाब में एक ही समस्या है।

इसे संभालने के बेहतर तरीके हो सकते हैं। अगर किसी को आंतरिक EqualToFluentValidationPropertyValidator कक्षा से सीधे तर्क शामिल करने का तरीका पता है, तो मुझे इसे सुनना अच्छा लगेगा।

2

यह @cryss जवाब पर आधारित है

RuleFor(x => x.HasToBeChecked) 
     .Equal(x => true) 
     .WithMessage("Required"); 

आप अतिरिक्त संपत्ति