MVC 不显眼的动态值范围验证 [英] MVC unobtrusive range validation of dynamic values

查看:19
本文介绍了MVC 不显眼的动态值范围验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的模型上有一个值,该值必须在我模型上的其他两个值的范围内.

例如:

公共类 RangeValidationSampleModel{整数值{得到;放;}int MinValue { 获取;放;}int MaxValue { 得到;放;}}

当然,我不能将这些 Min/MaxValues 传递到我的 DataAnnotations 属性中,因为它们必须是常量值.

我确定我需要构建自己的验证属性,但我还没有做这么多,也无法思考它应该如何工作.

我已经搜索了大约一个小时,并且看到了各种构建自定义验证的解决方案,但找不到任何使用 MVC3 不显眼的验证来解决这个特定问题的方法.

解决方案

您可以为此目的编写自定义验证属性:

public class DynamicRangeValidator : ValidationAttribute, IClientValidatable{私有只读字符串_minPropertyName;私有只读字符串_maxPropertyName;公共动态范围验证器(字符串 minPropertyName,字符串 maxPropertyName){_minPropertyName = minPropertyName;_maxPropertyName = maxPropertyName;}受保护的覆盖 ValidationResult IsValid(object value, ValidationContext validationContext){var minProperty = validationContext.ObjectType.GetProperty(_minPropertyName);var maxProperty = validationContext.ObjectType.GetProperty(_maxPropertyName);如果(minProperty == null){return new ValidationResult(string.Format("Unknown property {0}", _minPropertyName));}如果(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) 值;if (currentValue <= minValue || currentValue >= maxValue){返回新的验证结果(字符串.格式(错误信息,最小值,最大值));}返回空;}公共 IEnumerableGetClientValidationRules(ModelMetadata 元数据,ControllerContext 上下文){var 规则 = 新的 ModelClientValidationRule{ValidationType = "动态范围",ErrorMessage = this.ErrorMessage,};rule.ValidationParameters["minvalueproperty"] = _minPropertyName;rule.ValidationParameters["maxvalueproperty"] = _maxPropertyName;收益回报规则;}}

然后用它装饰你的视图模型:

公共类 RangeValidationSampleModel{[DynamicRangeValidator("MinValue", "MaxValue", ErrorMessage = "值必须介于 {0} 和 {1}")]公共 int 值 { 得到;放;}公共 int MinValue { 获取;放;}公共 int MaxValue { 获取;放;}}

然后你可以有一个控制器来提供一个视图:

公共类 HomeController : 控制器{公共 ActionResult 索引(){返回视图(新的 RangeValidationSampleModel{值 = 5,最小值 = 6,最大值 = 8});}[HttpPost]公共 ActionResult 索引(RangeValidationSampleModel 模型){返回视图(模型);}}

当然还有一个观点:

@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'],功能(选项){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);返回假;}返回真;}, '');@using (Html.BeginForm()){<div>@Html.LabelFor(x => x.Value)@Html.EditorFor(x => x.Value)@Html.ValidationMessageFor(x => x.Value)

<div>@Html.LabelFor(x => x.MinValue)@Html.EditorFor(x => x.MinValue)

<div>@Html.LabelFor(x => x.MaxValue)@Html.EditorFor(x => x.MaxValue)

<button type="submit">OK</button>}

显然,自定义适配器注册应该在外部 javascript 文件中执行以避免污染视图,但为了这篇文章的目的和简洁性,我将它放在视图中.

I have a value on my model, that must fall within the range of two other values on my model.

For example:

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

    int MinValue { get; set; }

    int MaxValue { get; set; }
}

Of course, I can't pass these Min/MaxValues into my DataAnnotations attributes, as they have to be constant values.

I'm sure I need to build my own validation attribute, but I haven't done this much and can't wrap my mind around how it should work.

I've searched for about an hour, and have seen all sorts of solutions for building custom validation, but can't find anything to solve this particular problem using MVC3 unobtrusive validation.

解决方案

You could write a custom validation attribute for this purpose:

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;
    }
}

and then decorate your view model with it:

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; }
}

then you could have a controller serving a view:

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);
    }
}

and a view of course:

@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>
}

Obviously the custom adapter registration should be performed in an external javascript file to avoid polluting the view but for the purpose and conciseness of this post I have put it inside the view.

这篇关于MVC 不显眼的动态值范围验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆