16

मेरे पास मेरे मॉडल पर एक मूल्य है, जो मेरे मॉडल पर दो अन्य मूल्यों की सीमा के भीतर होना चाहिए।एमवीसी गतिशील मानों की एमवीसी अविभाज्य सीमा सत्यापन

उदाहरण के लिए:

public class RangeValidationSampleModel 
{ 
    int Value { get; set; } 

    int MinValue { get; set; } 

    int MaxValue { get; set; } 
} 
बेशक

, मैं इन न्यूनतम/MaxValues ​​पारित नहीं हो सकता मेरी DataAnnotations में जिम्मेदार बताते हैं, जैसा कि वे निरंतर मूल्यों रहना होगा।

मुझे यकीन है कि मुझे अपनी खुद की सत्यापन विशेषता बनाने की ज़रूरत है, लेकिन मैंने यह नहीं किया है और यह मेरे दिमाग को लपेट नहीं सकता है कि इसे कैसे काम करना चाहिए।

मैंने लगभग एक घंटे की खोज की है, और कस्टम सत्यापन के निर्माण के लिए सभी प्रकार के समाधान देखे हैं, लेकिन एमवीसी 3 अविभाज्य सत्यापन का उपयोग करके इस विशेष समस्या को हल करने के लिए कुछ भी नहीं मिला है।

+0

क्या यह क्लाइंट साइड सत्यापन होना चाहिए? –

+1

यह बेहतर होगा। हम इस साइट को एमवीसी 2 से एमवीसी 3 में परिवर्तित कर रहे हैं, और वर्तमान में, एमवीसी 2 सत्यापन क्लाइंट साइड काम कर रहा है, इसलिए मैं इसे इस तरह से काम करना चाहता हूं। लेकिन यदि संभव हो, तो मैं अविभाज्य सत्यापन का उपयोग करना चाहता हूं। वर्तमान सत्यापन बहुत उलझन में है। :) –

उत्तर

34

आप इस उद्देश्य के लिए एक कस्टम मान्यता विशेषता लिख ​​सकते हैं:

public class DynamicRangeValidator : ValidationAttribute, IClientValidatable 
{ 
    private readonly string _minPropertyName; 
    private readonly string _maxPropertyName; 
    public DynamicRangeValidator(string minPropertyName, string maxPropertyName) 
    { 
     _minPropertyName = minPropertyName; 
     _maxPropertyName = maxPropertyName; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var minProperty = validationContext.ObjectType.GetProperty(_minPropertyName); 
     var maxProperty = validationContext.ObjectType.GetProperty(_maxPropertyName); 
     if (minProperty == null) 
     { 
      return new ValidationResult(string.Format("Unknown property {0}", _minPropertyName)); 
     } 
     if (maxProperty == null) 
     { 
      return new ValidationResult(string.Format("Unknown property {0}", _maxPropertyName)); 
     } 

     int minValue = (int)minProperty.GetValue(validationContext.ObjectInstance, null); 
     int maxValue = (int)maxProperty.GetValue(validationContext.ObjectInstance, null); 
     int currentValue = (int)value; 
     if (currentValue <= minValue || currentValue >= maxValue) 
     { 
      return new ValidationResult(
       string.Format(
        ErrorMessage, 
        minValue, 
        maxValue 
       ) 
      ); 
     } 

     return null; 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     var rule = new ModelClientValidationRule 
     { 
      ValidationType = "dynamicrange", 
      ErrorMessage = this.ErrorMessage, 
     }; 
     rule.ValidationParameters["minvalueproperty"] = _minPropertyName; 
     rule.ValidationParameters["maxvalueproperty"] = _maxPropertyName; 
     yield return rule; 
    } 
} 

और फिर इसे के साथ अपने दृश्य मॉडल को सजाने:

public class RangeValidationSampleModel 
{ 
    [DynamicRangeValidator("MinValue", "MaxValue", ErrorMessage = "Value must be between {0} and {1}")] 
    public int Value { get; set; } 
    public int MinValue { get; set; } 
    public int MaxValue { get; set; } 
} 

तो आप एक नियंत्रक एक दृश्य की सेवा हो सकता है:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(new RangeValidationSampleModel 
     { 
      Value = 5, 
      MinValue = 6, 
      MaxValue = 8 
     }); 
    } 

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

और पाठ्यक्रम का एक दृश्य:

@model RangeValidationSampleModel 

<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 type="text/javascript"> 
    $.validator.unobtrusive.adapters.add('dynamicrange', ['minvalueproperty', 'maxvalueproperty'], 
     function (options) { 
      options.rules['dynamicrange'] = options.params; 
      if (options.message != null) { 
       $.validator.messages.dynamicrange = options.message; 
      } 
     } 
    ); 

    $.validator.addMethod('dynamicrange', function (value, element, params) { 
     var minValue = parseInt($('input[name="' + params.minvalueproperty + '"]').val(), 10); 
     var maxValue = parseInt($('input[name="' + params.maxvalueproperty + '"]').val(), 10); 
     var currentValue = parseInt(value, 10); 
     if (isNaN(minValue) || isNaN(maxValue) || isNaN(currentValue) || minValue >= currentValue || currentValue >= maxValue) { 
      var message = $(element).attr('data-val-dynamicrange'); 
      $.validator.messages.dynamicrange = $.validator.format(message, minValue, maxValue); 
      return false; 
     } 
     return true; 
    }, ''); 
</script> 

@using (Html.BeginForm()) 
{ 
    <div> 
     @Html.LabelFor(x => x.Value) 
     @Html.EditorFor(x => x.Value) 
     @Html.ValidationMessageFor(x => x.Value) 
    </div> 
    <div> 
     @Html.LabelFor(x => x.MinValue) 
     @Html.EditorFor(x => x.MinValue) 
    </div> 
    <div> 
     @Html.LabelFor(x => x.MaxValue) 
     @Html.EditorFor(x => x.MaxValue) 
    </div> 
    <button type="submit">OK</button> 
} 

जाहिर है कस्टम एडाप्टर पंजीकरण बाहरी जावास्क्रिप्ट फ़ाइल में दृश्य प्रदूषण से बचने के लिए किया जाना चाहिए, लेकिन इस पोस्ट के उद्देश्य और एकरूपता के लिए मैंने इसे दृश्य में रखा है।

+1

धन्यवाद डारिन, यह कमाल है! मुझे जावास्क्रिप्ट कोड में दो छोटे बदलाव करना पड़ा। 'IsNaN' चेक को उलट दिया गया था ('! 'को हटा देना था), और मैंने न्यूनतम/अधिकतम चेक w /' isNaN' चेक भी स्थानांतरित कर दिया ताकि संदेश ठीक से सेट हो जाए। –

+0

@ जेराडरोस, वास्तव में, मेरे कोड में एक गलती थी। मैंने इसे अभी तय कर लिया है। यदि आप इसके साथ मुद्दों को देखते हैं तो आपको मेरा जवाब भी अपडेट करने में संकोच नहीं करना चाहिए। –

+0

इसके लिए धन्यवाद। मैंने इसे संपादित करने पर विचार किया, लेकिन ऐसा लगता है कि मुझे अभी तक ऐसा करने की अनुमति नहीं है (मुझे लगता है कि यह 2k पर है)। –

2

कस्टम सत्यापन गुण वास्तव में एक अच्छा विचार है। की तरह कुछ (कुछ टुकड़ा o'mine को खोदकर निकाल पाया जो जहां थोड़ी देर पहले जानता है):

public sealed class MustBeGreaterThan : ValidationAttribute 
{ 
    private const string _defaultErrorMessage = "'{0}' must be greater than '{1}'"; 
    private string _basePropertyName; 

    public MustBeGreaterThan(string basePropertyName) 
     : base(_defaultErrorMessage) 
    { 
     _basePropertyName = basePropertyName; 
    } 

    //Override default FormatErrorMessage Method 
    public override string FormatErrorMessage(string name) 
    { 
     return string.Format(_defaultErrorMessage, name, _basePropertyName); 
    } 

    //Override IsValid 
    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var basePropertyInfo = validationContext.ObjectType.GetProperty(_basePropertyName); 
     var lowerBound = (int)basePropertyInfo.GetValue(validationContext.ObjectInstance, null); 
     var thisValue = (int)value; 

     if (thisValue < lowerBound) 
     { 
      var message = FormatErrorMessage(validationContext.DisplayName); 
      return new ValidationResult(message); 
     } 

     //value validated 
     return null; 
    } 
} 

public sealed class MustBeLowerThan : ValidationAttribute 
{ 
    private const string _defaultErrorMessage = "'{0}' must be lower than '{1}'"; 
    private string _basePropertyName; 

    public MustBeLowerThan(string basePropertyName) 
     : base(_defaultErrorMessage) 
    { 
     _basePropertyName = basePropertyName; 
    } 

    //Override default FormatErrorMessage Method 
    public override string FormatErrorMessage(string name) 
    { 
     return string.Format(_defaultErrorMessage, name, _basePropertyName); 
    } 

    //Override IsValid 
    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var basePropertyInfo = validationContext.ObjectType.GetProperty(_basePropertyName); 
     var upperBound = (int)basePropertyInfo.GetValue(validationContext.ObjectInstance, null); 
     var thisValue = (int)value; 

     if (thisValue > upperBound) 
     { 
      var message = FormatErrorMessage(validationContext.DisplayName); 
      return new ValidationResult(message); 
     } 

     //value validated 
     return null; 
    } 
} 

फिर अपने वर्ग

public class RangeValidationSampleModel 
{ 
    [MustBeGreaterThan("MinValue")] 
    [MustBeLowerThan("MaxValue")] 
    int Value { get; set; } 

    int MinValue { get; set; } 

    int MaxValue { get; set; } 
} 

सजाने और तुम जाना

+0

धन्यवाद @alex। ऐसा लगता है कि यह क्लाइंट-साइड अविभाज्य सत्यापन के साथ काम करेगा, हालांकि, क्या होगा? –

0

अच्छा होना चाहिए आप तो क्लाइंट साइड सत्यापन की आवश्यकता है इसे कस्टम होना होगा। मैं हाल ही में यहां पर एक अच्छी पोस्ट को देखा (डैरिन मास्को में नहीं कर सकते इसे खोजने लगते हैं?) फिर भी - इस ग्राहक सत्यापन होने की अनुमति देगा: http://blogs.msdn.com/b/simonince/archive/2011/02/04/conditional-validation-in-asp-net-mvc-3.aspx

सर्वर साइड IValidateableObject के द्वारा नियंत्रित किया जा सकता है या Dynamic Range Validation in ASP.NET MVC 2

आदि आदि पर सर्वर की तरफ, लेकिन मुझे लगता है कि आप ग्राहक पक्ष को कुंजी होने के लिए चाहते हैं।

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