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

How do I get the model validation decorations output to my view?

我的 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,我宁愿让它预先做尽可能多的验证,而不是像检查字符串长度这样简单地往返于服务器。

现在我必须硬编码 <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 "";
        }

    }
}

没有您希望的直接方法。如果您使用 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。这也是我改编上面代码的地方。