如何将模型验证装饰输出到我的视图?

时间:2015-01-07 19:48:36

标签: c# asp.net-mvc asp.net-mvc-4

我的MVC应用程序中有以下数据模型

[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }

在我使用AngularJS的视图中,我宁愿让它在前面进行尽可能多的验证,而不是像检查字符串的长度一样简单地到服务器。 / p>

现在我必须硬编码<input ng-minlength="6" ng-maxlength="100" /> - 但是有没有办法从模型的装饰中获取这些数字?这是我希望可以做的一些伪代码:

<input
    ng-minlength="@Html.ValidationFor(m => m.Password).MinimumLength"
    ng-maxlength="@Html.ValidationFor(m => m.Password).MaximumLength" />

同样,如果使用[EmailAddress]修饰模型,是否可以将用于输出的正则表达式输出到我的视图中?


修改!

主要感谢@ChrisPratt指出我正确的方向!我在那里使用他的基本代码来制作我需要的帮助器。这不是完美的,但这是我的第一次拍摄并且有效。

现在我可以使用以下

@Html.ValidationAttributesFor(m => m.Password, ValidationHelper.ValidationAttributresEnum.MinimumLength)

这会叫这个班级

namespace System.Web.Mvc
{
    public static class ValidationHelper
    {
        public enum ValidationAttributresEnum
        {
            MinimumLength,
            MaximumLength
        }

        public static string ValidationAttributesFor<TParameter, TValue>(this HtmlHelper<TParameter> htmlHelper, Expression<Func<TParameter, TValue>> expression, ValidationAttributresEnum val)
        {
            var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            var validators = ModelValidatorProviders.Providers.GetValidators(metadata, htmlHelper.ViewContext);
            var rules = validators.SelectMany(v => v.GetClientValidationRules()).ToList();

            if (rules.Any(x => x is ModelClientValidationStringLengthRule))
            {
                var p = rules.FirstOrDefault(x => x is ModelClientValidationStringLengthRule).ValidationParameters;
                if(val.Equals(ValidationAttributresEnum.MinimumLength)){
                    return p["min"].ToString();
                }

                if (val.Equals(ValidationAttributresEnum.MaximumLength))
                {
                    return p["max"].ToString();
                }
            }

            return "";
        }

    }
}

1 个答案:

答案 0 :(得分:3)

没有像你希望的直接方式。如果您使用editor templates,则可以通过ViewData.ModelMetadata获取有关该模板内该属性的信息。这让你轻松掌握了一些东西。您可以使用ViewData.ModelMetadata.IsRequired确定是否已设置[Required]属性。同样,您可以通过ViewData.ModelMetadata.DisplayFormatString获取格式字符串之类的内容。对于您的数据类型(DataType.EmailAddress等),您可以从ViewData.ModelMetadata.DataTypeName获取。但是,这只会告诉您已设置的类型,而不是用于验证它的正则表达式或其他任何内容。

对于更复杂的验证规则,您需要以下内容:

@{
    var htmlAttributes = new Dictionary<string, string>();

    foreach(var validator in ViewData.ModelMetadata.GetValidators(ViewContext).SelectMany(v => v.GetClientValidationRules())) {
        var parameters = validator.ValidationParameters;

        if(validator is ModelClientValidationRegexRule) {
            htmlAttributes.Add("ng-pattern", parameters["pattern"]);
        } else if(validator is ModelClientValidationRangeRule) {
            htmlAttributes.Add("ng-minlength", parameters["min"]);
            htmlAttributes.Add("ng-maxlength", parameters["max"]);
        } else if(validator is ModelClientValidationStringLengthRule) {
            htmlAttributes.Add("ng-minlength", parameters["minlength"]);
            htmlAttributes.Add("ng-maxlength", parameters["maxlength"]);
        }
    }
}

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, htmlAttributes)

您可以并且可能应该将代码分解为类似HtmlHelper之类的扩展方法,因此您只需调用扩展方法并获取属性字典即可。有关示例,请参阅https://gist.github.com/andybooth/1029068。这也是我改编上述代码的地方。