提问人:UserControl 提问时间:6/22/2011 更新时间:11/15/2013 访问量:29636
RequiredAttribute 和 AllowEmptyString=true ASP.NET MVC 3 非侵入式验证
RequiredAttribute with AllowEmptyString=true in ASP.NET MVC 3 unobtrusive validation
问:
如果我的视图模型中有声明,则验证总是在空输入上触发。我找到了这篇文章,解释了为什么会发生这种情况。您知道是否有可用的修复程序吗?如果没有,你如何处理?[Required(AllowEmptyStrings = true)]
答:
23赞
Jon Galloway
6/28/2011
#1
注意:我假设您有 AllowEmptyStrings = true,因为您还在 Web 场景之外使用视图模型;否则,在 Web 场景中拥有允许空字符串的 Required 属性似乎没有多大意义。
有三个步骤可以处理此问题:
- 创建添加该验证参数的自定义属性适配器
- 将适配器注册为适配器工厂
- 重写 jQuery 验证函数,以在存在该属性时允许空字符串
第 1 步:自定义属性适配器
我修改了 RequiredAttributeAdapter 以添加该逻辑:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace CustomAttributes
{
/// <summary>Provides an adapter for the <see cref="T:System.Runtime.CompilerServices.RequiredAttributeAttribute" /> attribute.</summary>
public class RequiredAttributeAdapter : DataAnnotationsModelValidator<RequiredAttribute>
{
/// <summary>Initializes a new instance of the <see cref="T:System.Runtime.CompilerServices.RequiredAttributeAttribute" /> class.</summary>
/// <param name="metadata">The model metadata.</param>
/// <param name="context">The controller context.</param>
/// <param name="attribute">The required attribute.</param>
public RequiredAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredAttribute attribute)
: base(metadata, context, attribute)
{
}
/// <summary>Gets a list of required-value client validation rules.</summary>
/// <returns>A list of required-value client validation rules.</returns>
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
var rule = new ModelClientValidationRequiredRule(base.ErrorMessage);
if (base.Attribute.AllowEmptyStrings)
{
//setting "true" rather than bool true which is serialized as "True"
rule.ValidationParameters["allowempty"] = "true";
}
return new ModelClientValidationRequiredRule[] { rule };
}
}
}
第2步。在您的 global.asax / Application_Start() 中注册此内容
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(typeof(RequiredAttribute),
(metadata, controllerContext, attribute) => new CustomAttributes.RequiredAttributeAdapter(metadata,
controllerContext, (RequiredAttribute)attribute));
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
第 3 步。重写 jQuery“required”验证函数
这是使用 jQuery.validator.addMethod() 调用完成的,添加我们的自定义逻辑,然后调用原始函数 - 您可以在此处阅读有关此方法的更多信息。如果在整个站点中使用它,则可能在从 _Layout.cshtml 引用的脚本文件中。下面是一个示例脚本块,您可以将其放入页面进行测试:
<script>
jQuery.validator.methods.oldRequired = jQuery.validator.methods.required;
jQuery.validator.addMethod("required", function (value, element, param) {
if ($(element).attr('data-val-required-allowempty') == 'true') {
return true;
}
return jQuery.validator.methods.oldRequired.call(this, value, element, param);
},
jQuery.validator.messages.required // use default message
);
</script>
评论
0赞
UserControl
6/28/2011
谢谢你的努力,乔恩!不幸的是,它对我不起作用,我仍然看到“字段为必填项”消息:(我仔细检查了您的代码是否使用 VS 和浏览器调试器执行,并且我没有任何可能干扰的自定义脚本或与验证相关的代码。我使用jQuery 1.4.1。这会是问题所在吗?
0赞
UserControl
6/28/2011
是的,你是对的,我需要 Web 场景之外的功能(我的应用程序服务层执行类似的验证检查以达到 DRY)。
0赞
Tz_
6/29/2011
+1 这似乎是一个不错的解决方案,我想知道为什么它不起作用。但是,如果在 AllowEmptyStrings 的情况下适配器中不返回验证规则(空数组),也许可以简化它。然后,您可以省去客户端的魔术。然后,您还可以轻松检查输入中是否正确省略了必需的属性。如果它仍然不起作用,则应调试适配器代码,并查看是否正确调用它(如果注册正常)。
0赞
Jon Galloway
6/29/2011
这有“在我的机器上工作”的承诺;-)我列出的脚本块紧接在调用 /Scripts/jquery.validate.js 和 /Scripts/jquery.validate.unobtrusive.js 之后。我正在使用 jQuery 1.5.1 的新 MVC 3 项目。我将尝试发布示例项目,以便您可以进行比较。
0赞
Jon Galloway
7/2/2011
我很好奇 - 什么不起作用?它是 Javascript 参考吗?
16赞
Rick Arthur
9/9/2013
#2
我没有使用“Required”属性来修饰值,而是使用以下方法。我发现这是解决这个问题的最简单方法。
[显示格式 (ConvertEmptyStringToNull=false) ]
评论
0赞
Andy White
12/5/2013
我同意 - 这似乎是处理此问题的最简单方法。如果要允许空字符串,只需在保存之前在控制器中将 null 改回 “” 即可!
3赞
Mark Rucker
10/21/2015
美丽![必需]的这个缺点多年来一直让我在多个 asp.net 网站上感到恼火。(我现在同时使用 [Required(AllowEmptyStrings = true)、DisplayFormat(ConvertEmptyStringToNull=false)],效果很好。
0赞
AH.
12/3/2015
很好的答案。多谢。
0赞
Patrick Montelo
2/17/2016
+10 给 Rick 和 Mark,用于缓解 MVC 空字符串的痛苦,同时使用 DisplayFormat(ConvertEmptyStringToNull=false) 和 Required(AllowEmptyStrings = true)
评论