如何将模型验证装饰输出到我的视图?
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。这也是我改编上面代码的地方。
我的 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。这也是我改编上面代码的地方。